From 9aa4058f4e369c86d8b2aa232ab97d4c2e67297b Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 25 Jan 2024 12:57:12 +0530 Subject: [PATCH 01/53] feat: deployment files for riskFundV2 --- deploy/006-risk-fund-v2.ts | 17 ++ deployments/bscmainnet/RiskFundV2.json | 92 +++++-- .../e599bc05495d18590ac88167d546a0ef.json | 228 ++++++++++++++++++ 3 files changed, 323 insertions(+), 14 deletions(-) create mode 100644 deploy/006-risk-fund-v2.ts create mode 100644 deployments/bscmainnet/solcInputs/e599bc05495d18590ac88167d546a0ef.json diff --git a/deploy/006-risk-fund-v2.ts b/deploy/006-risk-fund-v2.ts new file mode 100644 index 00000000..229994de --- /dev/null +++ b/deploy/006-risk-fund-v2.ts @@ -0,0 +1,17 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +const func = async ({ getNamedAccounts, deployments }: HardhatRuntimeEnvironment) => { + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy("RiskFundV2", { + contract: "RiskFundV2", + from: deployer, + args: [], + log: true, + autoMine: true, + }); +}; + +func.tags = ["RiskFundV2"]; + +export default func; diff --git a/deployments/bscmainnet/RiskFundV2.json b/deployments/bscmainnet/RiskFundV2.json index f465190d..1d134775 100644 --- a/deployments/bscmainnet/RiskFundV2.json +++ b/deployments/bscmainnet/RiskFundV2.json @@ -1,5 +1,5 @@ { - "address": "0x5FA4E699eAFcf277d2Ed968bb9bc78F2fE9d04A3", + "address": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", "abi": [ { "inputs": [], @@ -270,6 +270,31 @@ "name": "SweepToken", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepTokenFromPool", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -512,6 +537,29 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepTokenFromPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -573,28 +621,28 @@ "type": "function" } ], - "transactionHash": "0x21e0a82fb96ff4c820c9b6e4e5e3fdec06a1fc46b247d1fae57f234972903ee9", + "transactionHash": "0x7d93e90484be2ae340f2d9eb4389ebdbd012eb0f0161cf5a5c8b98c1a8a237e4", "receipt": { "to": null, "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0x5FA4E699eAFcf277d2Ed968bb9bc78F2fE9d04A3", - "transactionIndex": 87, - "gasUsed": "1345522", + "contractAddress": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", + "transactionIndex": 42, + "gasUsed": "1417978", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7a03c99c60b8c380a8c9fc2160d8666793def7cbab31edf62519860aee564a2c", - "transactionHash": "0x21e0a82fb96ff4c820c9b6e4e5e3fdec06a1fc46b247d1fae57f234972903ee9", + "blockHash": "0xa2f1b69e987fa3f01fdf9be5ad673c9e4370c6c9396a9786b1d5178d8c4587bb", + "transactionHash": "0x7d93e90484be2ae340f2d9eb4389ebdbd012eb0f0161cf5a5c8b98c1a8a237e4", "logs": [], - "blockNumber": 35140358, - "cumulativeGasUsed": "10844978", + "blockNumber": 35547098, + "cumulativeGasUsed": "5087006", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "ee8827a99e03cdf6f6a94fb8782ddf44", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"poolReserve\",\"type\":\"uint256\"}],\"name\":\"InsufficientPoolReserve\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRiskFundConverter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortfallAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsDecreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldRiskFundConverter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newRiskFundConverter\",\"type\":\"address\"}],\"name\":\"RiskFundConverterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newShortfallContract\",\"type\":\"address\"}],\"name\":\"ShortfallContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLoopsLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolAssetsFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"riskFundConverter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"riskFundConverter_\",\"type\":\"address\"}],\"name\":\"setRiskFundConverter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"updatePoolState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"details\":\"This contract does not support BNB\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"custom:event\":\"ConvertibleBaseAssetUpdated emit on success\",\"details\":\"Convertible base asset setter\",\"params\":{\"convertibleBaseAsset_\":\"Address of the convertible base asset\"}},\"setRiskFundConverter(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when risk fund converter address is zero\",\"custom:event\":\"RiskFundConverterUpdated emit on success\",\"details\":\"Risk fund converter setter\",\"params\":{\"riskFundConverter_\":\"Address of the risk fund converter\"}},\"setShortfallContractAddress(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"custom:event\":\"ShortfallContractUpdated emit on success\",\"details\":\"Shortfall contract address setter\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zeroZeroValueNotAllowed is thrown when amount is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"Amount need to sweep for the pool\",\"to\":\"Address to which assets will be transferred\",\"tokenAddress\":\"Address of the asset(token)\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"transferReserveForAuction(address,uint256)\":{\"custom:access\":\"Only Shortfall contract\",\"custom:error\":\"InvalidShortfallAddress is thrown when caller is not shortfall contractInsufficientPoolReserve is thrown when pool reserve is less than the amount needed\",\"custom:event\":\"TransferredReserveForAuction emit on success\",\"details\":\"Transfer tokens for auction to shortfall contract\",\"params\":{\"amount\":\"Amount to be transferred to the shortfall\",\"comptroller\":\"Comptroller of the pool\"},\"returns\":{\"_0\":\"Amount of tokens transferred to the shortfall\"}},\"updatePoolState(address,address,uint256)\":{\"custom:access\":\"Only RiskFundConverter contract\",\"custom:error\":\"InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\",\"custom:event\":\"PoolAssetsIncreased emits on success\",\"details\":\"Update the reserve of the asset for the specific pool after transferring to risk fund\",\"params\":{\"amount\":\"Amount transferred for the pool\",\"asset\":\"Address of the asset(token)\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"RiskFundV2\",\"version\":1},\"userdoc\":{\"errors\":{\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientPoolReserve(address,uint256,uint256)\":[{\"notice\":\"Error is thrown when pool reserve is less than the amount needed\"}],\"InvalidRiskFundConverter()\":[{\"notice\":\"Error is thrown when updatePoolState is not called by riskFundConverter\"}],\"InvalidShortfallAddress()\":[{\"notice\":\"Error is thrown when transferReserveForAuction is called by non shortfall address\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset address is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDecreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\"},\"PoolAssetsIncreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred to this contract\"},\"RiskFundConverterUpdated(address,address)\":{\"notice\":\"Emitted when risk fund converter address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"convertibleBaseAsset()\":{\"notice\":\"Address of base asset\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"maxLoopsLimit()\":{\"notice\":\"Limit for the loops to avoid the DOSThis state is deprecated, using it to prevent storage collision\"},\"poolAssetsFunds(address,address)\":{\"notice\":\"Available asset's fund per pool in RiskFund Comptroller(pool) -> Asset -> amount\"},\"riskFundConverter()\":{\"notice\":\"Risk fund converter address\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"shortfall()\":{\"notice\":\"Address of shortfall contract\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"Function to sweep baseAsset for pool, Tokens are sent to address(to)\"}},\"notice\":\"Contract with basic features to hold base asset for different Comptrollers\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ProtocolReserve/RiskFundV2.sol\":\"RiskFundV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IRiskFundConverter {\\n function updateAssetsState(address comptroller, address asset) external;\\n\\n function getPools(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb7335d0d343100ca6294c5858193f52462d1818212ff4435c14da961af87a39e\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\n\\n/// @title ReserveHelpersStorage\\n/// @author Venus\\n/// @dev Reserve helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract ReserveHelpersStorage is Ownable2StepUpgradeable {\\n /// @notice Deprecated slot for assetReserves mapping\\n bytes32 private __deprecatedSlot1;\\n\\n /// @notice Available asset's fund per pool in RiskFund\\n /// Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) public poolAssetsFunds;\\n\\n /// @notice Deprecated slot for poolRegistry address\\n bytes32 private __deprecatedSlot2;\\n /// @notice Deprecated slot for status variable\\n bytes32 private __deprecatedSlot3;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n uint256[46] private __gap;\\n}\\n\\n/// @title MaxLoopsLimitHelpersStorage\\n/// @author Venus\\n/// @dev Max loop limit helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract MaxLoopsLimitHelpersStorage {\\n /// @notice Limit for the loops to avoid the DOS\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 public maxLoopsLimit;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[49] private __gap;\\n}\\n\\n/// @title RiskFundV1Storage\\n/// @author Venus\\n/// @dev Risk fund V1 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV1Storage is ReserveHelpersStorage, MaxLoopsLimitHelpersStorage {\\n /// @notice Address of base asset\\n address public convertibleBaseAsset;\\n /// @notice Address of shortfall contract\\n address public shortfall;\\n\\n /// @notice This state is deprecated, using it to prevent storage collision\\n address private pancakeSwapRouter;\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 private minAmountToConvert;\\n}\\n\\n/// @title RiskFundV2Storage\\n/// @author Venus\\n/// @dev Risk fund V2 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeable {\\n /// @notice Risk fund converter address\\n address public riskFundConverter;\\n}\\n\",\"keccak256\":\"0x0620187dca927191ab256ea20e42416883380690e54ba344807867adba01d7fb\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { IRiskFund } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IRiskFundConverter } from \\\"../Interfaces/IRiskFundConverter.sol\\\";\\nimport { RiskFundV2Storage } from \\\"./RiskFundStorage.sol\\\";\\n\\n/// @title RiskFundV2\\n/// @author Venus\\n/// @notice Contract with basic features to hold base asset for different Comptrollers\\n/// @dev This contract does not support BNB\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Emitted when convertible base asset address is updated\\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\\n\\n /// @notice Emitted when risk fund converter address is updated\\n event RiskFundConverterUpdated(address indexed oldRiskFundConverter, address indexed newRiskFundConverter);\\n\\n /// @notice Emitted when shortfall contract address is updated\\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\\n\\n /// @notice Emitted when reserves are transferred for auction\\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred to this contract\\n event PoolAssetsIncreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\\n event PoolAssetsDecreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Error is thrown when updatePoolState is not called by riskFundConverter\\n error InvalidRiskFundConverter();\\n\\n /// @notice Error is thrown when transferReserveForAuction is called by non shortfall address\\n error InvalidShortfallAddress();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice Error is thrown when pool reserve is less than the amount needed\\n error InsufficientPoolReserve(address comptroller, uint256 amount, uint256 poolReserve);\\n\\n /// @dev Convertible base asset setter\\n /// @param convertibleBaseAsset_ Address of the convertible base asset\\n /// @custom:event ConvertibleBaseAssetUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\\n /// @custom:access Only Governance\\n function setConvertibleBaseAsset(address convertibleBaseAsset_) external onlyOwner {\\n ensureNonzeroAddress(convertibleBaseAsset_);\\n emit ConvertibleBaseAssetUpdated(convertibleBaseAsset, convertibleBaseAsset_);\\n convertibleBaseAsset = convertibleBaseAsset_;\\n }\\n\\n /// @dev Risk fund converter setter\\n /// @param riskFundConverter_ Address of the risk fund converter\\n /// @custom:event RiskFundConverterUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when risk fund converter address is zero\\n /// @custom:access Only Governance\\n function setRiskFundConverter(address riskFundConverter_) external onlyOwner {\\n ensureNonzeroAddress(riskFundConverter_);\\n emit RiskFundConverterUpdated(riskFundConverter, riskFundConverter_);\\n riskFundConverter = riskFundConverter_;\\n }\\n\\n /// @dev Shortfall contract address setter\\n /// @param shortfallContractAddress_ Address of the auction contract\\n /// @custom:event ShortfallContractUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n /// @custom:access Only Governance\\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\\n ensureNonzeroAddress(shortfallContractAddress_);\\n emit ShortfallContractUpdated(shortfall, shortfallContractAddress_);\\n shortfall = shortfallContractAddress_;\\n }\\n\\n /// @dev Transfer tokens for auction to shortfall contract\\n /// @param comptroller Comptroller of the pool\\n /// @param amount Amount to be transferred to the shortfall\\n /// @return Amount of tokens transferred to the shortfall\\n /// @custom:event TransferredReserveForAuction emit on success\\n /// @custom:error InvalidShortfallAddress is thrown when caller is not shortfall contract\\n /// @custom:error InsufficientPoolReserve is thrown when pool reserve is less than the amount needed\\n /// @custom:access Only Shortfall contract\\n function transferReserveForAuction(address comptroller, uint256 amount)\\n external\\n override\\n nonReentrant\\n returns (uint256)\\n {\\n uint256 poolReserve = poolAssetsFunds[comptroller][convertibleBaseAsset];\\n\\n if (msg.sender != shortfall) {\\n revert InvalidShortfallAddress();\\n }\\n if (amount > poolReserve) {\\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\\n }\\n\\n unchecked {\\n poolAssetsFunds[comptroller][convertibleBaseAsset] = poolReserve - amount;\\n }\\n\\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall, amount);\\n emit TransferredReserveForAuction(comptroller, amount);\\n\\n return amount;\\n }\\n\\n /// @notice Function to sweep baseAsset for pool, Tokens are sent to address(to)\\n /// @param tokenAddress Address of the asset(token)\\n /// @param to Address to which assets will be transferred\\n /// @param amount Amount need to sweep for the pool\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /**\\n * @notice Get the Amount of the Base asset in the risk fund for the specific pool.\\n * @param comptroller Comptroller address(pool).\\n * @return Base Asset's reserve in risk fund.\\n */\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256) {\\n return poolAssetsFunds[comptroller][convertibleBaseAsset];\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Address of the asset(token)\\n /// @param amount Amount transferred for the pool\\n /// @custom:event PoolAssetsIncreased emits on success\\n /// @custom:error InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\\n /// @custom:access Only RiskFundConverter contract\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) public {\\n if (msg.sender != riskFundConverter) {\\n revert InvalidRiskFundConverter();\\n }\\n\\n poolAssetsFunds[comptroller][asset] += amount;\\n emit PoolAssetsIncreased(comptroller, asset, amount);\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\\n function preSweepToken(address tokenAddress, uint256 amount) internal {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n\\n address[] memory pools = IRiskFundConverter(riskFundConverter).getPools(tokenAddress);\\n\\n uint256 assetReserves;\\n uint256 poolsLength = pools.length;\\n for (uint256 i; i < poolsLength; ) {\\n assetReserves += poolAssetsFunds[pools[i]][tokenAddress];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256 balanceDiff = balance - assetReserves;\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n uint256 distributedShare;\\n for (uint256 i; i < poolsLength; ) {\\n if (poolAssetsFunds[pools[i]][tokenAddress] != 0) {\\n uint256 poolAmountShare;\\n if (i < (poolsLength - 1)) {\\n poolAmountShare = (poolAssetsFunds[pools[i]][tokenAddress] * amount) / assetReserves;\\n distributedShare += poolAmountShare;\\n } else {\\n poolAmountShare = amountDiff - distributedShare;\\n }\\n poolAssetsFunds[pools[i]][tokenAddress] -= poolAmountShare;\\n emit PoolAssetsDecreased(pools[i], tokenAddress, poolAmountShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe79f3802602fe5b406a3c374360009eb92e9545aee1ac833916af6c749979a0e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061178c806100206000396000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063715018a6116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102d1578063e30c3978146102e5578063f2fde38b146102f657600080fd5b8063b4a0bdf3146102b7578063be26317e146102c857600080fd5b806379ba5097116100b257806379ba5097146102635780638da5cb5b1461026b578063a69bd19e1461027c57600080fd5b8063715018a61461024857806377d4937f1461025057600080fd5b80632eef9172116101245780635dbe3533116101095780635dbe3533146101f7578063601bb5a91461022257806364aff9ec1461023557600080fd5b80632eef9172146101d057806353ac3537146101e457600080fd5b80630a9837c5146101565780630e32cb861461017c57806319b1faef146101915780632e688141146101bd575b600080fd5b61016961016436600461138d565b610309565b6040519081526020015b60405180910390f35b61018f61018a3660046113b9565b610468565b005b61012e546101a5906001600160a01b031681565b6040516001600160a01b039091168152602001610173565b61018f6101cb3660046113b9565b61047c565b610163546101a5906001600160a01b031681565b61018f6101f23660046113dd565b610503565b61016961020536600461141e565b60ca60209081526000928352604080842090915290825290205481565b61018f6102303660046113b9565b6105d8565b61018f6102433660046113dd565b61065f565b61018f610707565b61018f61025e3660046113b9565b61071b565b61018f6107a2565b6033546001600160a01b03166101a5565b61016961028a3660046113b9565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101a5565b61016960fb5481565b61012d546101a5906001600160a01b031681565b6065546001600160a01b03166101a5565b61018f6103043660046113b9565b610847565b60006103136108d0565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e54909116331461037c576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808311156103d4576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461041892908116911685610945565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161045391815260200190565b60405180910390a25050600161013155919050565b6104706109c5565b61047981610a39565b50565b6104846109c5565b61048d81610b48565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610548576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca602090815260408083209386168352929052908120805483929061057f908490611486565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105cb91815260200190565b60405180910390a3505050565b6105e06109c5565b6105e981610b48565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6106676109c5565b61066f6108d0565b61067883610b48565b61068182610b48565b61068a81610b88565b826106958183610bc2565b6106a96001600160a01b0382168484610945565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516106ee91815260200190565b60405180910390a350610702600161013155565b505050565b61070f6109c5565b6107196000610fe6565b565b6107236109c5565b61072c81610b48565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461083e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103cb565b61047981610fe6565b61084f6109c5565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556108986033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002610131540361093d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103cb565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610702908490611017565b6033546001600160a01b03163314610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103cb565b6001600160a01b038116610acf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103cb565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b038116610479576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003610479576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610c22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c46919061149e565b905080821115610c82576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610ce7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610d2d91908101906114f6565b8051909150600090815b81811015610db65760ca6000858381518110610d5557610d556115d9565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610dac9190611486565b9250600101610d37565b506000610dc38386611608565b905085811015610fdd578086036000805b84811015610fd95760ca6000888381518110610df257610df26115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014610fd1576000610e52600187611608565b821015610ee457868a60ca60008b8681518110610e7157610e716115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054610ec7919061161f565b610ed1919061165c565b9050610edd8184611486565b9250610ef1565b610eee8385611608565b90505b8060ca60008a8581518110610f0857610f086115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b031681526020019081526020016000206000828254610f629190611608565b925050819055508a6001600160a01b0316888381518110610f8557610f856115d9565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd8432083604051610fc791815260200190565b60405180910390a3505b600101610dd4565b5050505b50505050505050565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561047981611119565b600061106c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111839092919063ffffffff16565b905080516000148061108d57508080602001905181019061108d9190611697565b610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103cb565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060611192848460008561119a565b949350505050565b60608247101561122c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103cb565b600080866001600160a01b0316858760405161124891906116e9565b60006040518083038185875af1925050503d8060008114611285576040519150601f19603f3d011682016040523d82523d6000602084013e61128a565b606091505b509150915061129b878383876112a6565b979650505050505050565b6060831561132f578251600003611328576001600160a01b0385163b611328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103cb565b5081611192565b61119283838151156113445781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103cb9190611705565b6001600160a01b038116811461047957600080fd5b600080604083850312156113a057600080fd5b82356113ab81611378565b946020939093013593505050565b6000602082840312156113cb57600080fd5b81356113d681611378565b9392505050565b6000806000606084860312156113f257600080fd5b83356113fd81611378565b9250602084013561140d81611378565b929592945050506040919091013590565b6000806040838503121561143157600080fd5b823561143c81611378565b9150602083013561144c81611378565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561149957611499611457565b500190565b6000602082840312156114b057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80516114f181611378565b919050565b6000602080838503121561150957600080fd5b825167ffffffffffffffff8082111561152157600080fd5b818501915085601f83011261153557600080fd5b815181811115611547576115476114b7565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561158a5761158a6114b7565b6040529182528482019250838101850191888311156115a857600080fd5b938501935b828510156115cd576115be856114e6565b845293850193928501926115ad565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008282101561161a5761161a611457565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561165757611657611457565b500290565b600082611692577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156116a957600080fd5b815180151581146113d657600080fd5b60005b838110156116d45781810151838201526020016116bc565b838111156116e3576000848401525b50505050565b600082516116fb8184602087016116b9565b9190910192915050565b60208152600082518060208401526117248160408501602087016116b9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea26469706673582212209c38201c74c3ca466d0abbc6a00c9bd8bb8ed5a5a063d3202f59106f43fcc5a764736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063715018a6116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102d1578063e30c3978146102e5578063f2fde38b146102f657600080fd5b8063b4a0bdf3146102b7578063be26317e146102c857600080fd5b806379ba5097116100b257806379ba5097146102635780638da5cb5b1461026b578063a69bd19e1461027c57600080fd5b8063715018a61461024857806377d4937f1461025057600080fd5b80632eef9172116101245780635dbe3533116101095780635dbe3533146101f7578063601bb5a91461022257806364aff9ec1461023557600080fd5b80632eef9172146101d057806353ac3537146101e457600080fd5b80630a9837c5146101565780630e32cb861461017c57806319b1faef146101915780632e688141146101bd575b600080fd5b61016961016436600461138d565b610309565b6040519081526020015b60405180910390f35b61018f61018a3660046113b9565b610468565b005b61012e546101a5906001600160a01b031681565b6040516001600160a01b039091168152602001610173565b61018f6101cb3660046113b9565b61047c565b610163546101a5906001600160a01b031681565b61018f6101f23660046113dd565b610503565b61016961020536600461141e565b60ca60209081526000928352604080842090915290825290205481565b61018f6102303660046113b9565b6105d8565b61018f6102433660046113dd565b61065f565b61018f610707565b61018f61025e3660046113b9565b61071b565b61018f6107a2565b6033546001600160a01b03166101a5565b61016961028a3660046113b9565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101a5565b61016960fb5481565b61012d546101a5906001600160a01b031681565b6065546001600160a01b03166101a5565b61018f6103043660046113b9565b610847565b60006103136108d0565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e54909116331461037c576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808311156103d4576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461041892908116911685610945565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161045391815260200190565b60405180910390a25050600161013155919050565b6104706109c5565b61047981610a39565b50565b6104846109c5565b61048d81610b48565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610548576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca602090815260408083209386168352929052908120805483929061057f908490611486565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105cb91815260200190565b60405180910390a3505050565b6105e06109c5565b6105e981610b48565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6106676109c5565b61066f6108d0565b61067883610b48565b61068182610b48565b61068a81610b88565b826106958183610bc2565b6106a96001600160a01b0382168484610945565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516106ee91815260200190565b60405180910390a350610702600161013155565b505050565b61070f6109c5565b6107196000610fe6565b565b6107236109c5565b61072c81610b48565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461083e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103cb565b61047981610fe6565b61084f6109c5565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556108986033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002610131540361093d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103cb565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610702908490611017565b6033546001600160a01b03163314610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103cb565b6001600160a01b038116610acf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103cb565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b038116610479576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003610479576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610c22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c46919061149e565b905080821115610c82576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610ce7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610d2d91908101906114f6565b8051909150600090815b81811015610db65760ca6000858381518110610d5557610d556115d9565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610dac9190611486565b9250600101610d37565b506000610dc38386611608565b905085811015610fdd578086036000805b84811015610fd95760ca6000888381518110610df257610df26115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014610fd1576000610e52600187611608565b821015610ee457868a60ca60008b8681518110610e7157610e716115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054610ec7919061161f565b610ed1919061165c565b9050610edd8184611486565b9250610ef1565b610eee8385611608565b90505b8060ca60008a8581518110610f0857610f086115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b031681526020019081526020016000206000828254610f629190611608565b925050819055508a6001600160a01b0316888381518110610f8557610f856115d9565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd8432083604051610fc791815260200190565b60405180910390a3505b600101610dd4565b5050505b50505050505050565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561047981611119565b600061106c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111839092919063ffffffff16565b905080516000148061108d57508080602001905181019061108d9190611697565b610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103cb565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060611192848460008561119a565b949350505050565b60608247101561122c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103cb565b600080866001600160a01b0316858760405161124891906116e9565b60006040518083038185875af1925050503d8060008114611285576040519150601f19603f3d011682016040523d82523d6000602084013e61128a565b606091505b509150915061129b878383876112a6565b979650505050505050565b6060831561132f578251600003611328576001600160a01b0385163b611328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103cb565b5081611192565b61119283838151156113445781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103cb9190611705565b6001600160a01b038116811461047957600080fd5b600080604083850312156113a057600080fd5b82356113ab81611378565b946020939093013593505050565b6000602082840312156113cb57600080fd5b81356113d681611378565b9392505050565b6000806000606084860312156113f257600080fd5b83356113fd81611378565b9250602084013561140d81611378565b929592945050506040919091013590565b6000806040838503121561143157600080fd5b823561143c81611378565b9150602083013561144c81611378565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561149957611499611457565b500190565b6000602082840312156114b057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80516114f181611378565b919050565b6000602080838503121561150957600080fd5b825167ffffffffffffffff8082111561152157600080fd5b818501915085601f83011261153557600080fd5b815181811115611547576115476114b7565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561158a5761158a6114b7565b6040529182528482019250838101850191888311156115a857600080fd5b938501935b828510156115cd576115be856114e6565b845293850193928501926115ad565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008282101561161a5761161a611457565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561165757611657611457565b500290565b600082611692577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156116a957600080fd5b815180151581146113d657600080fd5b60005b838110156116d45781810151838201526020016116bc565b838111156116e3576000848401525b50505050565b600082516116fb8184602087016116b9565b9190910192915050565b60208152600082518060208401526117248160408501602087016116b9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea26469706673582212209c38201c74c3ca466d0abbc6a00c9bd8bb8ed5a5a063d3202f59106f43fcc5a764736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "e599bc05495d18590ac88167d546a0ef", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"poolReserve\",\"type\":\"uint256\"}],\"name\":\"InsufficientPoolReserve\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRiskFundConverter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortfallAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsDecreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldRiskFundConverter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newRiskFundConverter\",\"type\":\"address\"}],\"name\":\"RiskFundConverterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newShortfallContract\",\"type\":\"address\"}],\"name\":\"ShortfallContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepTokenFromPool\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLoopsLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolAssetsFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"riskFundConverter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"riskFundConverter_\",\"type\":\"address\"}],\"name\":\"setRiskFundConverter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepTokenFromPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"updatePoolState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"details\":\"This contract does not support BNB\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"custom:event\":\"ConvertibleBaseAssetUpdated emit on success\",\"details\":\"Convertible base asset setter\",\"params\":{\"convertibleBaseAsset_\":\"Address of the convertible base asset\"}},\"setRiskFundConverter(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when risk fund converter address is zero\",\"custom:event\":\"RiskFundConverterUpdated emit on success\",\"details\":\"Risk fund converter setter\",\"params\":{\"riskFundConverter_\":\"Address of the risk fund converter\"}},\"setShortfallContractAddress(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"custom:event\":\"ShortfallContractUpdated emit on success\",\"details\":\"Shortfall contract address setter\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zeroZeroValueNotAllowed is thrown when amount is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"Amount need to sweep for the pool\",\"to\":\"Address to which assets will be transferred\",\"tokenAddress\":\"Address of the asset(token)\"}},\"sweepTokenFromPool(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zeroZeroValueNotAllowed is thrown when amount is zero\",\"custom:event\":\"Emits sweepTokenFromPool event on success\",\"params\":{\"amount\":\"Amount need to sweep from the pool\",\"comptroller\":\"Pool address to which assets will be transferred\",\"tokenAddress\":\"Address of the asset(token)\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"transferReserveForAuction(address,uint256)\":{\"custom:access\":\"Only Shortfall contract\",\"custom:error\":\"InvalidShortfallAddress is thrown when caller is not shortfall contractInsufficientPoolReserve is thrown when pool reserve is less than the amount needed\",\"custom:event\":\"TransferredReserveForAuction emit on success\",\"details\":\"Transfer tokens for auction to shortfall contract\",\"params\":{\"amount\":\"Amount to be transferred to the shortfall\",\"comptroller\":\"Comptroller of the pool\"},\"returns\":{\"_0\":\"Amount of tokens transferred to the shortfall\"}},\"updatePoolState(address,address,uint256)\":{\"custom:access\":\"Only RiskFundConverter contract\",\"custom:error\":\"InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\",\"custom:event\":\"PoolAssetsIncreased emits on success\",\"details\":\"Update the reserve of the asset for the specific pool after transferring to risk fund\",\"params\":{\"amount\":\"Amount transferred for the pool\",\"asset\":\"Address of the asset(token)\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"RiskFundV2\",\"version\":1},\"userdoc\":{\"errors\":{\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientPoolReserve(address,uint256,uint256)\":[{\"notice\":\"Error is thrown when pool reserve is less than the amount needed\"}],\"InvalidRiskFundConverter()\":[{\"notice\":\"Error is thrown when updatePoolState is not called by riskFundConverter\"}],\"InvalidShortfallAddress()\":[{\"notice\":\"Error is thrown when transferReserveForAuction is called by non shortfall address\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset address is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDecreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\"},\"PoolAssetsIncreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred to this contract\"},\"RiskFundConverterUpdated(address,address)\":{\"notice\":\"Emitted when risk fund converter address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"},\"SweepTokenFromPool(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept and transferred from pool\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"convertibleBaseAsset()\":{\"notice\":\"Address of base asset\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"maxLoopsLimit()\":{\"notice\":\"Limit for the loops to avoid the DOSThis state is deprecated, using it to prevent storage collision\"},\"poolAssetsFunds(address,address)\":{\"notice\":\"Available asset's fund per pool in RiskFund Comptroller(pool) -> Asset -> amount\"},\"riskFundConverter()\":{\"notice\":\"Risk fund converter address\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"shortfall()\":{\"notice\":\"Address of shortfall contract\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"Function to sweep baseAsset for pool, Tokens are sent to address(to)\"},\"sweepTokenFromPool(address,address,uint256)\":{\"notice\":\"Function to sweep token from pool\"}},\"notice\":\"Contract with basic features to hold base asset for different Comptrollers\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ProtocolReserve/RiskFundV2.sol\":\"RiskFundV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IRiskFundConverter {\\n function updateAssetsState(address comptroller, address asset) external;\\n\\n function getPools(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb7335d0d343100ca6294c5858193f52462d1818212ff4435c14da961af87a39e\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\n\\n/// @title ReserveHelpersStorage\\n/// @author Venus\\n/// @dev Reserve helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract ReserveHelpersStorage is Ownable2StepUpgradeable {\\n /// @notice Deprecated slot for assetReserves mapping\\n bytes32 private __deprecatedSlot1;\\n\\n /// @notice Available asset's fund per pool in RiskFund\\n /// Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) public poolAssetsFunds;\\n\\n /// @notice Deprecated slot for poolRegistry address\\n bytes32 private __deprecatedSlot2;\\n /// @notice Deprecated slot for status variable\\n bytes32 private __deprecatedSlot3;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n uint256[46] private __gap;\\n}\\n\\n/// @title MaxLoopsLimitHelpersStorage\\n/// @author Venus\\n/// @dev Max loop limit helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract MaxLoopsLimitHelpersStorage {\\n /// @notice Limit for the loops to avoid the DOS\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 public maxLoopsLimit;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[49] private __gap;\\n}\\n\\n/// @title RiskFundV1Storage\\n/// @author Venus\\n/// @dev Risk fund V1 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV1Storage is ReserveHelpersStorage, MaxLoopsLimitHelpersStorage {\\n /// @notice Address of base asset\\n address public convertibleBaseAsset;\\n /// @notice Address of shortfall contract\\n address public shortfall;\\n\\n /// @notice This state is deprecated, using it to prevent storage collision\\n address private pancakeSwapRouter;\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 private minAmountToConvert;\\n}\\n\\n/// @title RiskFundV2Storage\\n/// @author Venus\\n/// @dev Risk fund V2 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeable {\\n /// @notice Risk fund converter address\\n address public riskFundConverter;\\n}\\n\",\"keccak256\":\"0x0620187dca927191ab256ea20e42416883380690e54ba344807867adba01d7fb\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { IRiskFund } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IRiskFundConverter } from \\\"../Interfaces/IRiskFundConverter.sol\\\";\\nimport { RiskFundV2Storage } from \\\"./RiskFundStorage.sol\\\";\\n\\n/// @title RiskFundV2\\n/// @author Venus\\n/// @notice Contract with basic features to hold base asset for different Comptrollers\\n/// @dev This contract does not support BNB\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Emitted when convertible base asset address is updated\\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\\n\\n /// @notice Emitted when risk fund converter address is updated\\n event RiskFundConverterUpdated(address indexed oldRiskFundConverter, address indexed newRiskFundConverter);\\n\\n /// @notice Emitted when shortfall contract address is updated\\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\\n\\n /// @notice Emitted when reserves are transferred for auction\\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred to this contract\\n event PoolAssetsIncreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\\n event PoolAssetsDecreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Event emitted when tokens are swept and transferred from pool\\n event SweepTokenFromPool(address indexed token, address indexed comptroller, uint256 amount);\\n\\n /// @notice Error is thrown when updatePoolState is not called by riskFundConverter\\n error InvalidRiskFundConverter();\\n\\n /// @notice Error is thrown when transferReserveForAuction is called by non shortfall address\\n error InvalidShortfallAddress();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice Error is thrown when pool reserve is less than the amount needed\\n error InsufficientPoolReserve(address comptroller, uint256 amount, uint256 poolReserve);\\n\\n /// @dev Convertible base asset setter\\n /// @param convertibleBaseAsset_ Address of the convertible base asset\\n /// @custom:event ConvertibleBaseAssetUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\\n /// @custom:access Only Governance\\n function setConvertibleBaseAsset(address convertibleBaseAsset_) external onlyOwner {\\n ensureNonzeroAddress(convertibleBaseAsset_);\\n emit ConvertibleBaseAssetUpdated(convertibleBaseAsset, convertibleBaseAsset_);\\n convertibleBaseAsset = convertibleBaseAsset_;\\n }\\n\\n /// @dev Risk fund converter setter\\n /// @param riskFundConverter_ Address of the risk fund converter\\n /// @custom:event RiskFundConverterUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when risk fund converter address is zero\\n /// @custom:access Only Governance\\n function setRiskFundConverter(address riskFundConverter_) external onlyOwner {\\n ensureNonzeroAddress(riskFundConverter_);\\n emit RiskFundConverterUpdated(riskFundConverter, riskFundConverter_);\\n riskFundConverter = riskFundConverter_;\\n }\\n\\n /// @dev Shortfall contract address setter\\n /// @param shortfallContractAddress_ Address of the auction contract\\n /// @custom:event ShortfallContractUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n /// @custom:access Only Governance\\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\\n ensureNonzeroAddress(shortfallContractAddress_);\\n emit ShortfallContractUpdated(shortfall, shortfallContractAddress_);\\n shortfall = shortfallContractAddress_;\\n }\\n\\n /// @dev Transfer tokens for auction to shortfall contract\\n /// @param comptroller Comptroller of the pool\\n /// @param amount Amount to be transferred to the shortfall\\n /// @return Amount of tokens transferred to the shortfall\\n /// @custom:event TransferredReserveForAuction emit on success\\n /// @custom:error InvalidShortfallAddress is thrown when caller is not shortfall contract\\n /// @custom:error InsufficientPoolReserve is thrown when pool reserve is less than the amount needed\\n /// @custom:access Only Shortfall contract\\n function transferReserveForAuction(address comptroller, uint256 amount)\\n external\\n override\\n nonReentrant\\n returns (uint256)\\n {\\n uint256 poolReserve = poolAssetsFunds[comptroller][convertibleBaseAsset];\\n\\n if (msg.sender != shortfall) {\\n revert InvalidShortfallAddress();\\n }\\n if (amount > poolReserve) {\\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\\n }\\n\\n unchecked {\\n poolAssetsFunds[comptroller][convertibleBaseAsset] = poolReserve - amount;\\n }\\n\\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall, amount);\\n emit TransferredReserveForAuction(comptroller, amount);\\n\\n return amount;\\n }\\n\\n /// @notice Function to sweep baseAsset for pool, Tokens are sent to address(to)\\n /// @param tokenAddress Address of the asset(token)\\n /// @param to Address to which assets will be transferred\\n /// @param amount Amount need to sweep for the pool\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice Function to sweep token from pool\\n /// @param tokenAddress Address of the asset(token)\\n /// @param comptroller Pool address to which assets will be transferred\\n /// @param amount Amount need to sweep from the pool\\n /// @custom:event Emits sweepTokenFromPool event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zero\\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\\n /// @custom:access Only Governance\\n function sweepTokenFromPool(\\n address tokenAddress,\\n address comptroller,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(comptroller);\\n ensureNonzeroValue(amount);\\n\\n uint256 poolReserve = poolAssetsFunds[comptroller][tokenAddress];\\n\\n if (amount > poolReserve) {\\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\\n }\\n\\n unchecked {\\n poolAssetsFunds[comptroller][tokenAddress] = poolReserve - amount;\\n }\\n\\n IERC20Upgradeable(tokenAddress).safeTransfer(comptroller, amount);\\n\\n emit SweepTokenFromPool(tokenAddress, comptroller, amount);\\n }\\n\\n /**\\n * @notice Get the Amount of the Base asset in the risk fund for the specific pool.\\n * @param comptroller Comptroller address(pool).\\n * @return Base Asset's reserve in risk fund.\\n */\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256) {\\n return poolAssetsFunds[comptroller][convertibleBaseAsset];\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Address of the asset(token)\\n /// @param amount Amount transferred for the pool\\n /// @custom:event PoolAssetsIncreased emits on success\\n /// @custom:error InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\\n /// @custom:access Only RiskFundConverter contract\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) public {\\n if (msg.sender != riskFundConverter) {\\n revert InvalidRiskFundConverter();\\n }\\n\\n poolAssetsFunds[comptroller][asset] += amount;\\n emit PoolAssetsIncreased(comptroller, asset, amount);\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\\n function preSweepToken(address tokenAddress, uint256 amount) internal {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n\\n address[] memory pools = IRiskFundConverter(riskFundConverter).getPools(tokenAddress);\\n\\n uint256 assetReserves;\\n uint256 poolsLength = pools.length;\\n for (uint256 i; i < poolsLength; ) {\\n assetReserves += poolAssetsFunds[pools[i]][tokenAddress];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256 balanceDiff = balance - assetReserves;\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n uint256 distributedShare;\\n for (uint256 i; i < poolsLength; ) {\\n if (poolAssetsFunds[pools[i]][tokenAddress] != 0) {\\n uint256 poolAmountShare;\\n if (i < (poolsLength - 1)) {\\n poolAmountShare = (poolAssetsFunds[pools[i]][tokenAddress] * amount) / assetReserves;\\n distributedShare += poolAmountShare;\\n } else {\\n poolAmountShare = amountDiff - distributedShare;\\n }\\n poolAssetsFunds[pools[i]][tokenAddress] -= poolAmountShare;\\n emit PoolAssetsDecreased(pools[i], tokenAddress, poolAmountShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x311a4e348835634eaa4aaf08515f91552513cdf1f5a01c05bf75f939a294bf2e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506118db806100206000396000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c806377d4937f116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102ff578063e30c397814610313578063f2fde38b1461032457600080fd5b8063b4a0bdf3146102e5578063be26317e146102f657600080fd5b8063855a8dd2116100b2578063855a8dd2146102865780638da5cb5b14610299578063a69bd19e146102aa57600080fd5b806377d4937f1461026b57806379ba50971461027e57600080fd5b806353ac353711610124578063601bb5a911610109578063601bb5a91461023d57806364aff9ec14610250578063715018a61461026357600080fd5b806353ac3537146101ff5780635dbe35331461021257600080fd5b806319b1faef1161015557806319b1faef146101ac5780632e688141146101d85780632eef9172146101eb57600080fd5b80630a9837c5146101715780630e32cb8614610197575b600080fd5b61018461017f3660046114dc565b610337565b6040519081526020015b60405180910390f35b6101aa6101a5366004611508565b610496565b005b61012e546101c0906001600160a01b031681565b6040516001600160a01b03909116815260200161018e565b6101aa6101e6366004611508565b6104aa565b610163546101c0906001600160a01b031681565b6101aa61020d36600461152c565b610531565b61018461022036600461156d565b60ca60209081526000928352604080842090915290825290205481565b6101aa61024b366004611508565b610606565b6101aa61025e36600461152c565b61068d565b6101aa610735565b6101aa610279366004611508565b610749565b6101aa6107d0565b6101aa61029436600461152c565b610875565b6033546001600160a01b03166101c0565b6101846102b8366004611508565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101c0565b61018460fb5481565b61012d546101c0906001600160a01b031681565b6065546001600160a01b03166101c0565b6101aa610332366004611508565b610996565b6000610341610a1f565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e5490911633146103aa576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80831115610402576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461044692908116911685610a94565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161048191815260200190565b60405180910390a25050600161013155919050565b61049e610b14565b6104a781610b88565b50565b6104b2610b14565b6104bb81610c97565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610576576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca60209081526040808320938616835292905290812080548392906105ad9084906115d5565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105f991815260200190565b60405180910390a3505050565b61060e610b14565b61061781610c97565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610695610b14565b61069d610a1f565b6106a683610c97565b6106af82610c97565b6106b881610cd7565b826106c38183610d11565b6106d76001600160a01b0382168484610a94565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d58460405161071c91815260200190565b60405180910390a350610730600161013155565b505050565b61073d610b14565b6107476000611135565b565b610751610b14565b61075a81610c97565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461086c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103f9565b6104a781611135565b61087d610b14565b610885610a1f565b61088e83610c97565b61089782610c97565b6108a081610cd7565b6001600160a01b03808316600090815260ca602090815260408083209387168352929052205480821115610919576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260248101839052604481018290526064016103f9565b6001600160a01b03808416600090815260ca602090815260408083209388168084529390915290208383039055610951908484610a94565b826001600160a01b0316846001600160a01b03167f0e8a97dff226f3ada9da954f9bd38f73280b03ef851bfc7c97db1343f07bdbdc8460405161071c91815260200190565b61099e610b14565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556109e76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60026101315403610a8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103f9565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610730908490611166565b6033546001600160a01b03163314610747576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103f9565b6001600160a01b038116610c1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103f9565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b0381166104a7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000036104a7576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9591906115ed565b905080821115610dd1576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610e36573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610e7c9190810190611645565b8051909150600090815b81811015610f055760ca6000858381518110610ea457610ea4611728565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610efb91906115d5565b9250600101610e86565b506000610f128386611757565b90508581101561112c578086036000805b848110156111285760ca6000888381518110610f4157610f41611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014611120576000610fa1600187611757565b82101561103357868a60ca60008b8681518110610fc057610fc0611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054611016919061176e565b61102091906117ab565b905061102c81846115d5565b9250611040565b61103d8385611757565b90505b8060ca60008a858151811061105757611057611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546110b19190611757565b925050819055508a6001600160a01b03168883815181106110d4576110d4611728565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd843208360405161111691815260200190565b60405180910390a3505b600101610f23565b5050505b50505050505050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556104a781611268565b60006111bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166112d29092919063ffffffff16565b90508051600014806111dc5750808060200190518101906111dc91906117e6565b610730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103f9565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606112e184846000856112e9565b949350505050565b60608247101561137b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103f9565b600080866001600160a01b031685876040516113979190611838565b60006040518083038185875af1925050503d80600081146113d4576040519150601f19603f3d011682016040523d82523d6000602084013e6113d9565b606091505b50915091506113ea878383876113f5565b979650505050505050565b6060831561147e578251600003611477576001600160a01b0385163b611477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103f9565b50816112e1565b6112e183838151156114935781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f99190611854565b6001600160a01b03811681146104a757600080fd5b600080604083850312156114ef57600080fd5b82356114fa816114c7565b946020939093013593505050565b60006020828403121561151a57600080fd5b8135611525816114c7565b9392505050565b60008060006060848603121561154157600080fd5b833561154c816114c7565b9250602084013561155c816114c7565b929592945050506040919091013590565b6000806040838503121561158057600080fd5b823561158b816114c7565b9150602083013561159b816114c7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115e8576115e86115a6565b500190565b6000602082840312156115ff57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8051611640816114c7565b919050565b6000602080838503121561165857600080fd5b825167ffffffffffffffff8082111561167057600080fd5b818501915085601f83011261168457600080fd5b81518181111561169657611696611606565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811085821117156116d9576116d9611606565b6040529182528482019250838101850191888311156116f757600080fd5b938501935b8285101561171c5761170d85611635565b845293850193928501926116fc565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082821015611769576117696115a6565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156117a6576117a66115a6565b500290565b6000826117e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156117f857600080fd5b8151801515811461152557600080fd5b60005b8381101561182357818101518382015260200161180b565b83811115611832576000848401525b50505050565b6000825161184a818460208701611808565b9190910192915050565b6020815260008251806020840152611873816040850160208701611808565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220ae70b20469fe0d634614028f8d5ab4bd856fb444c39affcec03bff538f7033cd64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061016c5760003560e01c806377d4937f116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102ff578063e30c397814610313578063f2fde38b1461032457600080fd5b8063b4a0bdf3146102e5578063be26317e146102f657600080fd5b8063855a8dd2116100b2578063855a8dd2146102865780638da5cb5b14610299578063a69bd19e146102aa57600080fd5b806377d4937f1461026b57806379ba50971461027e57600080fd5b806353ac353711610124578063601bb5a911610109578063601bb5a91461023d57806364aff9ec14610250578063715018a61461026357600080fd5b806353ac3537146101ff5780635dbe35331461021257600080fd5b806319b1faef1161015557806319b1faef146101ac5780632e688141146101d85780632eef9172146101eb57600080fd5b80630a9837c5146101715780630e32cb8614610197575b600080fd5b61018461017f3660046114dc565b610337565b6040519081526020015b60405180910390f35b6101aa6101a5366004611508565b610496565b005b61012e546101c0906001600160a01b031681565b6040516001600160a01b03909116815260200161018e565b6101aa6101e6366004611508565b6104aa565b610163546101c0906001600160a01b031681565b6101aa61020d36600461152c565b610531565b61018461022036600461156d565b60ca60209081526000928352604080842090915290825290205481565b6101aa61024b366004611508565b610606565b6101aa61025e36600461152c565b61068d565b6101aa610735565b6101aa610279366004611508565b610749565b6101aa6107d0565b6101aa61029436600461152c565b610875565b6033546001600160a01b03166101c0565b6101846102b8366004611508565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101c0565b61018460fb5481565b61012d546101c0906001600160a01b031681565b6065546001600160a01b03166101c0565b6101aa610332366004611508565b610996565b6000610341610a1f565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e5490911633146103aa576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80831115610402576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461044692908116911685610a94565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161048191815260200190565b60405180910390a25050600161013155919050565b61049e610b14565b6104a781610b88565b50565b6104b2610b14565b6104bb81610c97565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610576576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca60209081526040808320938616835292905290812080548392906105ad9084906115d5565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105f991815260200190565b60405180910390a3505050565b61060e610b14565b61061781610c97565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610695610b14565b61069d610a1f565b6106a683610c97565b6106af82610c97565b6106b881610cd7565b826106c38183610d11565b6106d76001600160a01b0382168484610a94565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d58460405161071c91815260200190565b60405180910390a350610730600161013155565b505050565b61073d610b14565b6107476000611135565b565b610751610b14565b61075a81610c97565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461086c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103f9565b6104a781611135565b61087d610b14565b610885610a1f565b61088e83610c97565b61089782610c97565b6108a081610cd7565b6001600160a01b03808316600090815260ca602090815260408083209387168352929052205480821115610919576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260248101839052604481018290526064016103f9565b6001600160a01b03808416600090815260ca602090815260408083209388168084529390915290208383039055610951908484610a94565b826001600160a01b0316846001600160a01b03167f0e8a97dff226f3ada9da954f9bd38f73280b03ef851bfc7c97db1343f07bdbdc8460405161071c91815260200190565b61099e610b14565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556109e76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60026101315403610a8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103f9565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610730908490611166565b6033546001600160a01b03163314610747576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103f9565b6001600160a01b038116610c1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103f9565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b0381166104a7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000036104a7576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9591906115ed565b905080821115610dd1576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610e36573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610e7c9190810190611645565b8051909150600090815b81811015610f055760ca6000858381518110610ea457610ea4611728565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610efb91906115d5565b9250600101610e86565b506000610f128386611757565b90508581101561112c578086036000805b848110156111285760ca6000888381518110610f4157610f41611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014611120576000610fa1600187611757565b82101561103357868a60ca60008b8681518110610fc057610fc0611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054611016919061176e565b61102091906117ab565b905061102c81846115d5565b9250611040565b61103d8385611757565b90505b8060ca60008a858151811061105757611057611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546110b19190611757565b925050819055508a6001600160a01b03168883815181106110d4576110d4611728565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd843208360405161111691815260200190565b60405180910390a3505b600101610f23565b5050505b50505050505050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556104a781611268565b60006111bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166112d29092919063ffffffff16565b90508051600014806111dc5750808060200190518101906111dc91906117e6565b610730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103f9565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606112e184846000856112e9565b949350505050565b60608247101561137b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103f9565b600080866001600160a01b031685876040516113979190611838565b60006040518083038185875af1925050503d80600081146113d4576040519150601f19603f3d011682016040523d82523d6000602084013e6113d9565b606091505b50915091506113ea878383876113f5565b979650505050505050565b6060831561147e578251600003611477576001600160a01b0385163b611477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103f9565b50816112e1565b6112e183838151156114935781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f99190611854565b6001600160a01b03811681146104a757600080fd5b600080604083850312156114ef57600080fd5b82356114fa816114c7565b946020939093013593505050565b60006020828403121561151a57600080fd5b8135611525816114c7565b9392505050565b60008060006060848603121561154157600080fd5b833561154c816114c7565b9250602084013561155c816114c7565b929592945050506040919091013590565b6000806040838503121561158057600080fd5b823561158b816114c7565b9150602083013561159b816114c7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115e8576115e86115a6565b500190565b6000602082840312156115ff57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8051611640816114c7565b919050565b6000602080838503121561165857600080fd5b825167ffffffffffffffff8082111561167057600080fd5b818501915085601f83011261168457600080fd5b81518181111561169657611696611606565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811085821117156116d9576116d9611606565b6040529182528482019250838101850191888311156116f757600080fd5b938501935b8285101561171c5761170d85611635565b845293850193928501926116fc565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082821015611769576117696115a6565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156117a6576117a66115a6565b500290565b6000826117e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156117f857600080fd5b8151801515811461152557600080fd5b60005b8381101561182357818101518382015260200161180b565b83811115611832576000848401525b50505050565b6000825161184a818460208701611808565b9190910192915050565b6020815260008251806020840152611873816040850160208701611808565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220ae70b20469fe0d634614028f8d5ab4bd856fb444c39affcec03bff538f7033cd64736f6c634300080d0033", "devdoc": { "author": "Venus", "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", @@ -666,6 +714,16 @@ "tokenAddress": "Address of the asset(token)" } }, + "sweepTokenFromPool(address,address,uint256)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zeroZeroValueNotAllowed is thrown when amount is zero", + "custom:event": "Emits sweepTokenFromPool event on success", + "params": { + "amount": "Amount need to sweep from the pool", + "comptroller": "Pool address to which assets will be transferred", + "tokenAddress": "Address of the asset(token)" + } + }, "transferOwnership(address)": { "details": "Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner." }, @@ -757,6 +815,9 @@ "SweepToken(address,address,uint256)": { "notice": "Event emitted when tokens are swept" }, + "SweepTokenFromPool(address,address,uint256)": { + "notice": "Event emitted when tokens are swept and transferred from pool" + }, "TransferredReserveForAuction(address,uint256)": { "notice": "Emitted when reserves are transferred for auction" } @@ -789,6 +850,9 @@ }, "sweepToken(address,address,uint256)": { "notice": "Function to sweep baseAsset for pool, Tokens are sent to address(to)" + }, + "sweepTokenFromPool(address,address,uint256)": { + "notice": "Function to sweep token from pool" } }, "notice": "Contract with basic features to hold base asset for different Comptrollers", diff --git a/deployments/bscmainnet/solcInputs/e599bc05495d18590ac88167d546a0ef.json b/deployments/bscmainnet/solcInputs/e599bc05495d18590ac88167d546a0ef.json new file mode 100644 index 00000000..8371748c --- /dev/null +++ b/deployments/bscmainnet/solcInputs/e599bc05495d18590ac88167d546a0ef.json @@ -0,0 +1,228 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides 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} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling 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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(account),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling 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/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1967.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967 {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../Proxy.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.\n *\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\n * conflict with the storage layout of the implementation behind the proxy.\n *\n * _Available since v3.4._\n */\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the proxy with `beacon`.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\n * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity\n * constructor.\n *\n * Requirements:\n *\n * - `beacon` must be a contract with the interface {IBeacon}.\n */\n constructor(address beacon, bytes memory data) payable {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n\n /**\n * @dev Returns the current beacon address.\n */\n function _beacon() internal view virtual returns (address) {\n return _getBeacon();\n }\n\n /**\n * @dev Returns the current implementation address of the associated beacon.\n */\n function _implementation() internal view virtual override returns (address) {\n return IBeacon(_getBeacon()).implementation();\n }\n\n /**\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\n *\n * Requirements:\n *\n * - `beacon` must be a contract.\n * - The implementation returned by `beacon` must be a contract.\n */\n function _setBeacon(address beacon, bytes memory data) internal virtual {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../../access/Ownable.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\n * implementation contract, which is where they will delegate all function calls.\n *\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\n */\ncontract UpgradeableBeacon is IBeacon, Ownable {\n address private _implementation;\n\n /**\n * @dev Emitted when the implementation returned by the beacon is changed.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\n * beacon.\n */\n constructor(address implementation_) {\n _setImplementation(implementation_);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function implementation() public view virtual override returns (address) {\n return _implementation;\n }\n\n /**\n * @dev Upgrades the beacon to a new implementation.\n *\n * Emits an {Upgraded} event.\n *\n * Requirements:\n *\n * - msg.sender must be the owner of the contract.\n * - `newImplementation` must be a contract.\n */\n function upgradeTo(address newImplementation) public virtual onlyOwner {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation contract address for this beacon\n *\n * Requirements:\n *\n * - `newImplementation` must be a contract.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"UpgradeableBeacon: implementation is not a contract\");\n _implementation = newImplementation;\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/IERC1967.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967Upgrade is IERC1967 {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\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 * 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 default value returned by this function, unless\n * it's 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(address from, address to, uint256 amount) 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 `from` to `to`.\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(address from, address to, uint256 amount) 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 // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\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 unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\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 // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\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(address owner, address spender, uint256 amount) 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(address owner, address spender, uint256 amount) 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(address from, address to, uint256 amount) 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(address from, address to, uint256 amount) 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.9.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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\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/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlledV8\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\n /// @notice Access control manager contract\n IAccessControlManagerV8 private _accessControlManager;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when access control manager contract address is changed\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n /// @notice Thrown when the action is prohibited by AccessControlManager\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Sets the address of AccessControlManager\n * @dev Admin function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n * @custom:event Emits NewAccessControlManager event\n * @custom:access Only Governance\n */\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Returns the address of the access control manager contract\n */\n function accessControlManager() external view returns (IAccessControlManagerV8) {\n return _accessControlManager;\n }\n\n /**\n * @dev Internal function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n */\n function _setAccessControlManager(address accessControlManager_) internal {\n require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n address oldAccessControlManager = address(_accessControlManager);\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title IAccessControlManagerV8\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\n */\ninterface IAccessControlManagerV8 is IAccessControl {\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) external;\n\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface OracleInterface {\n function getPrice(address asset) external view returns (uint256);\n}\n\ninterface ResilientOracleInterface is OracleInterface {\n function updatePrice(address vToken) external;\n\n function updateAssetPrice(address asset) external;\n\n function getUnderlyingPrice(address vToken) external view returns (uint256);\n}\n\ninterface TwapInterface is OracleInterface {\n function updateTwap(address asset) external returns (uint256);\n}\n\ninterface BoundValidatorInterface {\n function validatePriceWithAnchorPrice(\n address asset,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface VBep20Interface is IERC20Metadata {\n /**\n * @notice Underlying asset for this VToken\n */\n function underlying() external view returns (address);\n}\n" + }, + "@venusprotocol/oracle/contracts/ResilientOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"./interfaces/VBep20Interface.sol\";\nimport \"./interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ResilientOracle\n * @author Venus\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\n * \n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\n * for attacking the protocol.\n * \n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\n * \n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \n * \n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\n * market. The upper bound ratio represents the deviation between reported price (the price that’s being\n * validated) and the anchor price (the price we are validating against) above which the reported price will\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\n * should be true:\n\n```\nanchorRatio = anchorPrice/reporterPrice\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\n```\n\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \n * \n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\n * oracle to be stagnant and treat it like it's disabled.\n */\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\n /**\n * @dev Oracle roles:\n * **main**: The most trustworthy price source\n * **pivot**: Price oracle used as a loose sanity checker\n * **fallback**: The backup source when main oracle price is invalidated\n */\n enum OracleRole {\n MAIN,\n PIVOT,\n FALLBACK\n }\n\n struct TokenConfig {\n /// @notice asset address\n address asset;\n /// @notice `oracles` stores the oracles based on their role in the following order:\n /// [main, pivot, fallback],\n /// It can be indexed with the corresponding enum OracleRole value\n address[3] oracles;\n /// @notice `enableFlagsForOracles` stores the enabled state\n /// for each oracle in the same order as `oracles`\n bool[3] enableFlagsForOracles;\n }\n\n uint256 public constant INVALID_PRICE = 0;\n\n /// @notice Native market address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable nativeMarket;\n\n /// @notice VAI address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vai;\n\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\n /// and can serve as any underlying asset of a market that supports native tokens\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Bound validator contract address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n BoundValidatorInterface public immutable boundValidator;\n\n mapping(address => TokenConfig) private tokenConfigs;\n\n event TokenConfigAdded(\n address indexed asset,\n address indexed mainOracle,\n address indexed pivotOracle,\n address fallbackOracle\n );\n\n /// Event emitted when an oracle is set\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\n\n /// Event emitted when an oracle is enabled or disabled\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\n\n /**\n * @notice Checks whether an address is null or not\n */\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /**\n * @notice Checks whether token config exists by checking whether asset is null address\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\n * @param asset asset address\n */\n modifier checkTokenConfigExistence(address asset) {\n if (tokenConfigs[asset].asset == address(0)) revert(\"token config must exist\");\n _;\n }\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\n /// (e.g vETH on ethereum would not be supported, only vWETH)\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\n /// Set to address(0) of VAI is not existent.\n /// @param _boundValidator Address of the bound validator contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address nativeMarketAddress,\n address vaiAddress,\n BoundValidatorInterface _boundValidator\n ) notNullAddress(address(_boundValidator)) {\n nativeMarket = nativeMarketAddress;\n vai = vaiAddress;\n boundValidator = _boundValidator;\n\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract admin and sets the BoundValidator contract address\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n }\n\n /**\n * @notice Pauses oracle\n * @custom:access Only Governance\n */\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n _pause();\n }\n\n /**\n * @notice Unpauses oracle\n * @custom:access Only Governance\n */\n function unpause() external {\n _checkAccessAllowed(\"unpause()\");\n _unpause();\n }\n\n /**\n * @notice Batch sets token configs\n * @param tokenConfigs_ Token config array\n * @custom:access Only Governance\n * @custom:error Throws a length error if the length of the token configs array is 0\n */\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\n if (tokenConfigs_.length == 0) revert(\"length can't be 0\");\n uint256 numTokenConfigs = tokenConfigs_.length;\n for (uint256 i; i < numTokenConfigs; ) {\n setTokenConfig(tokenConfigs_[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Sets oracle for a given asset and role.\n * @dev Supplied asset **must** exist and main oracle may not be null\n * @param asset Asset address\n * @param oracle Oracle address\n * @param role Oracle role\n * @custom:access Only Governance\n * @custom:error Null address error if main-role oracle address is null\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\n */\n function setOracle(\n address asset,\n address oracle,\n OracleRole role\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"setOracle(address,address,uint8)\");\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\"can't set zero address to main oracle\");\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\n emit OracleSet(asset, oracle, uint256(role));\n }\n\n /**\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\n * @param asset Asset address\n * @param role Oracle role\n * @param enable Enabled boolean of the oracle\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n */\n function enableOracle(\n address asset,\n OracleRole role,\n bool enable\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"enableOracle(address,uint8,bool)\");\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\n emit OracleEnabled(asset, uint256(role), enable);\n }\n\n /**\n * @notice Updates the TWAP pivot oracle price.\n * @dev This function should always be called before calling getUnderlyingPrice\n * @param vToken vToken address\n */\n function updatePrice(address vToken) external override {\n address asset = _getUnderlyingAsset(vToken);\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @notice Updates the pivot oracle price. Currently using TWAP\n * @dev This function should always be called before calling getPrice\n * @param asset asset address\n */\n function updateAssetPrice(address asset) external {\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @dev Gets token config by asset address\n * @param asset asset address\n * @return tokenConfig Config for the asset\n */\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\n return tokenConfigs[asset];\n }\n\n /**\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\n * - Check if the oracle is paused globally\n * - Validate price from main oracle against pivot oracle\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\n * - Validate price from main oracle against fallback oracle if the second validation failed\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\n * main oracle price is returned.\n * @param vToken vToken address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n\n address asset = _getUnderlyingAsset(vToken);\n return _getPrice(asset);\n }\n\n /**\n * @notice Gets price of the asset\n * @param asset asset address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getPrice(address asset) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n return _getPrice(asset);\n }\n\n /**\n * @notice Sets/resets single token configs.\n * @dev main oracle **must not** be a null address\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress is thrown if asset address is null\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(\n tokenConfig.asset,\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\n );\n }\n\n /**\n * @notice Gets oracle and enabled status by asset address\n * @param asset asset address\n * @param role Oracle role\n * @return oracle Oracle address based on role\n * @return enabled Enabled flag of the oracle based on token config\n */\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\n oracle = tokenConfigs[asset].oracles[uint256(role)];\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\n }\n\n function _getPrice(address asset) internal view returns (uint256) {\n uint256 pivotPrice = INVALID_PRICE;\n\n // Get pivot oracle price, Invalid price if not available or error\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracleEnabled && pivotOracle != address(0)) {\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\n pivotPrice = pricePivot;\n } catch {}\n }\n\n // Compare main price and pivot price, return main price and if validation was successful\n // note: In case pivot oracle is not available but main price is available and\n // validation is successful, the main oracle price is returned.\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\n asset,\n pivotPrice,\n pivotOracleEnabled && pivotOracle != address(0)\n );\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\n\n // Compare fallback and pivot if main oracle comparision fails with pivot\n // Return fallback price when fallback price is validated successfully with pivot oracle\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\n\n // Lastly compare main price and fallback price\n if (\n mainPrice != INVALID_PRICE &&\n fallbackPrice != INVALID_PRICE &&\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\n ) {\n return mainPrice;\n }\n\n revert(\"invalid resilient oracle price\");\n }\n\n /**\n * @notice Gets a price for the provided asset\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\n * able to fetch a correct price\n * @param asset asset address\n * @param pivotPrice Pivot oracle price\n * @param pivotEnabled If pivot oracle is not empty and enabled\n * @return price USD price in scaled decimals\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\n * @return pivotValidated Boolean representing if the validation of main oracle price\n * and pivot oracle price were successful\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\n * address is null\n */\n function _getMainOraclePrice(\n address asset,\n uint256 pivotPrice,\n bool pivotEnabled\n ) internal view returns (uint256, bool) {\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\n if (mainOracleEnabled && mainOracle != address(0)) {\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\n if (!pivotEnabled) {\n return (mainOraclePrice, true);\n }\n if (pivotPrice == INVALID_PRICE) {\n return (mainOraclePrice, false);\n }\n return (\n mainOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\n * @param asset asset address\n * @return price USD price in 18 decimals\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\n * and pivot oracle price were successfull\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\n * address is null\n */\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\n if (fallbackEnabled && fallbackOracle != address(0)) {\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\n if (pivotPrice == INVALID_PRICE) {\n return (fallbackOraclePrice, false);\n }\n return (\n fallbackOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function returns the underlying asset of a vToken\n * @param vToken vToken address\n * @return asset underlying asset address\n */\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\n if (vToken == nativeMarket) {\n asset = NATIVE_TOKEN_ADDR;\n } else if (vToken == vai) {\n asset = vai;\n } else {\n asset = VBep20Interface(vToken).underlying();\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\nuint256 constant EXP_SCALE = 1e18;\n\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\nuint256 constant MANTISSA_ONE = EXP_SCALE;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\n" + }, + "@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title MaxLoopsLimitHelper\n * @author Venus\n * @notice Abstract contract used to avoid collection with too many items that would generate gas errors and DoS.\n */\nabstract contract MaxLoopsLimitHelper {\n // Limit for the loops to avoid the DOS\n uint256 public maxLoopsLimit;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when max loops limit is set\n event MaxLoopsLimitUpdated(uint256 oldMaxLoopsLimit, uint256 newmaxLoopsLimit);\n\n /// @notice Thrown an error on maxLoopsLimit exceeds for any loop\n error MaxLoopsLimitExceeded(uint256 loopsLimit, uint256 requiredLoops);\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function _setMaxLoopsLimit(uint256 limit) internal {\n require(limit > maxLoopsLimit, \"Comptroller: Invalid maxLoopsLimit\");\n\n uint256 oldMaxLoopsLimit = maxLoopsLimit;\n maxLoopsLimit = limit;\n\n emit MaxLoopsLimitUpdated(oldMaxLoopsLimit, limit);\n }\n\n /**\n * @notice Compare the maxLoopsLimit with number of the times loop iterate\n * @param len Length of the loops iterate\n * @custom:error MaxLoopsLimitExceeded error is thrown when loops length exceeds maxLoopsLimit\n */\n function _ensureMaxLoops(uint256 len) internal view {\n if (len > maxLoopsLimit) {\n revert MaxLoopsLimitExceeded(maxLoopsLimit, len);\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/validators.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\nerror ZeroAddressNotAllowed();\n\n/// @notice Thrown if the supplied value is 0 where it is not allowed\nerror ZeroValueNotAllowed();\n\n/// @notice Checks if the provided address is nonzero, reverts otherwise\n/// @param address_ Address to check\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\nfunction ensureNonzeroAddress(address address_) pure {\n if (address_ == address(0)) {\n revert ZeroAddressNotAllowed();\n }\n}\n\n/// @notice Checks if the provided value is nonzero, reverts otherwise\n/// @param value_ Value to check\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\nfunction ensureNonzeroValue(uint256 value_) pure {\n if (value_ == 0) {\n revert ZeroValueNotAllowed();\n }\n}\n" + }, + "contracts/Interfaces/IComptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IComptroller {\n function isComptroller() external view returns (bool);\n\n function markets(address) external view returns (bool);\n\n function getAllMarkets() external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IConverterNetwork.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAbstractTokenConverter } from \"../TokenConverter/IAbstractTokenConverter.sol\";\n\n/**\n * @title IConverterNetwork\n * @author Venus\n * @notice Interface implemented by `ConverterNetwork`.\n */\ninterface IConverterNetwork {\n /// @notice Adds new converter to the array\n /// @param _tokenConverter Address of the token converter\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Removes converter from the array\n /// @param _tokenConverter Address of the token converter\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice This function returns the array containing all the converters addresses\n /// @return Array containing all the converters addresses\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\n\n /// @notice This function checks for given address is converter or not\n /// @param _tokenConverter Address of the token converter\n /// @return boolean true if given address is converter otherwise false\n function isTokenConverter(address _tokenConverter) external view returns (bool);\n}\n" + }, + "contracts/Interfaces/IIncomeDestination.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IIncomeDestination {\n function updateAssetsState(address comptroller, address asset) external;\n}\n" + }, + "contracts/Interfaces/IPoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IPoolRegistry {\n /// @notice Get VToken in the Pool for an Asset\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\n\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION\n }\n\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) external;\n}\n" + }, + "contracts/Interfaces/IRiskFund.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IRiskFund\n * @author Venus\n * @notice Interface implemented by `RiskFund`.\n */\ninterface IRiskFund {\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updatePoolState(\n address comptroller,\n address asset,\n uint256 amount\n ) external;\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n\n/**\n * @title IRiskFundGetters\n * @author Venus\n * @notice Interface implemented by `RiskFund` for getter methods.\n */\ninterface IRiskFundGetters {\n function convertibleBaseAsset() external view returns (address);\n}\n" + }, + "contracts/Interfaces/IRiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IRiskFundConverter {\n function updateAssetsState(address comptroller, address asset) external;\n\n function getPools(address asset) external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IShortfall.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IShortfall\n * @author Venus\n * @notice Interface implemented by `Shortfall`.\n */\ninterface IShortfall {\n function convertibleBaseAsset() external returns (address);\n}\n" + }, + "contracts/Interfaces/IVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IVToken {\n function underlying() external view returns (address);\n}\n" + }, + "contracts/Interfaces/IXVSVault.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @title IXVSVaultProxy\n/// @author Venus\n/// @notice Interface implemented by `XVSVault`.\ninterface IXVSVault {\n function xvsStore() external view returns (address);\n}\n" + }, + "contracts/ProtocolReserve/ProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IProtocolShareReserve } from \"../Interfaces/IProtocolShareReserve.sol\";\nimport { IComptroller } from \"../Interfaces/IComptroller.sol\";\nimport { IPoolRegistry } from \"../Interfaces/IPoolRegistry.sol\";\nimport { IVToken } from \"../Interfaces/IVToken.sol\";\nimport { IIncomeDestination } from \"../Interfaces/IIncomeDestination.sol\";\n\nerror InvalidAddress();\nerror UnsupportedAsset();\nerror InvalidTotalPercentage();\nerror InvalidMaxLoopsLimit();\n\ncontract ProtocolShareReserve is\n AccessControlledV8,\n ReentrancyGuardUpgradeable,\n MaxLoopsLimitHelper,\n IProtocolShareReserve\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice protocol income is categorized into two schemas.\n /// The first schema is for spread income\n /// The second schema is for liquidation income\n enum Schema {\n PROTOCOL_RESERVES,\n ADDITIONAL_REVENUE\n }\n\n struct DistributionConfig {\n Schema schema;\n /// @dev percenatge is represented without any scale\n uint16 percentage;\n address destination;\n }\n\n /// @notice address of core pool comptroller contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n /// @notice address of WBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable WBNB;\n\n /// @notice address of vBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vBNB;\n\n /// @notice address of pool registry contract\n address public poolRegistry;\n\n uint16 public constant MAX_PERCENT = 1e4;\n\n /// @notice comptroller => asset => schema => balance\n mapping(address => mapping(address => mapping(Schema => uint256))) public assetsReserves;\n\n /// @notice asset => balance\n mapping(address => uint256) public totalAssetReserve;\n\n /// @notice configuration for different income distribution targets\n DistributionConfig[] public distributionTargets;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Event emitted after updating of the assets reserves.\n event AssetsReservesUpdated(\n address indexed comptroller,\n address indexed asset,\n uint256 amount,\n IncomeType incomeType,\n Schema schema\n );\n\n /// @notice Event emitted when an asset is released to a target\n event AssetReleased(\n address indexed destination,\n address indexed asset,\n Schema schema,\n uint256 percent,\n uint256 amount\n );\n\n /// @notice Event emitted when asset reserves state is updated\n event ReservesUpdated(\n address indexed comptroller,\n address indexed asset,\n Schema schema,\n uint256 oldBalance,\n uint256 newBalance\n );\n\n /// @notice Event emitted when distribution configuration is updated\n event DistributionConfigUpdated(\n address indexed destination,\n uint16 oldPercentage,\n uint16 newPercentage,\n Schema schema\n );\n\n /// @notice Event emitted when distribution configuration is added\n event DistributionConfigAdded(address indexed destination, uint16 percentage, Schema schema);\n\n /// @notice Event emitted when distribution configuration is removed\n event DistributionConfigRemoved(address indexed destination, uint16 percentage, Schema schema);\n\n /**\n * @dev Constructor to initialize the immutable variables\n * @param _corePoolComptroller The address of core pool comptroller\n * @param _wbnb The address of WBNB\n * @param _vbnb The address of vBNB\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _corePoolComptroller,\n address _wbnb,\n address _vbnb\n ) {\n ensureNonzeroAddress(_corePoolComptroller);\n ensureNonzeroAddress(_wbnb);\n ensureNonzeroAddress(_vbnb);\n\n CORE_POOL_COMPTROLLER = _corePoolComptroller;\n WBNB = _wbnb;\n vBNB = _vbnb;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @dev Initializes the deployer to owner.\n * @param _accessControlManager The address of ACM contract\n * @param _loopsLimit Limit for the loops in the contract to avoid DOS\n */\n function initialize(address _accessControlManager, uint256 _loopsLimit) external initializer {\n __AccessControlled_init(_accessControlManager);\n __ReentrancyGuard_init();\n _setMaxLoopsLimit(_loopsLimit);\n }\n\n /**\n * @dev Pool registry setter.\n * @param _poolRegistry Address of the pool registry\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n */\n function setPoolRegistry(address _poolRegistry) external onlyOwner {\n ensureNonzeroAddress(_poolRegistry);\n emit PoolRegistryUpdated(poolRegistry, _poolRegistry);\n poolRegistry = _poolRegistry;\n }\n\n /**\n * @dev Add or update destination targets based on destination address\n * @param configs configurations of the destinations.\n */\n function addOrUpdateDistributionConfigs(DistributionConfig[] calldata configs) external nonReentrant {\n _checkAccessAllowed(\"addOrUpdateDistributionConfigs(DistributionConfig[])\");\n\n for (uint256 i = 0; i < configs.length; ) {\n DistributionConfig memory _config = configs[i];\n ensureNonzeroAddress(_config.destination);\n\n bool updated = false;\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 j = 0; j < distributionTargetsLength; ) {\n DistributionConfig storage config = distributionTargets[j];\n\n if (_config.schema == config.schema && config.destination == _config.destination) {\n emit DistributionConfigUpdated(\n _config.destination,\n config.percentage,\n _config.percentage,\n _config.schema\n );\n config.percentage = _config.percentage;\n updated = true;\n break;\n }\n\n unchecked {\n ++j;\n }\n }\n\n if (!updated) {\n distributionTargets.push(_config);\n emit DistributionConfigAdded(_config.destination, _config.percentage, _config.schema);\n }\n\n unchecked {\n ++i;\n }\n }\n\n _ensurePercentages();\n _ensureMaxLoops(distributionTargets.length);\n }\n\n /**\n * @dev Remove destionation target if percentage is 0\n * @param schema schema of the configuration\n * @param destination destination address of the configuration\n */\n function removeDistributionConfig(Schema schema, address destination) external {\n _checkAccessAllowed(\"removeDistributionConfig(Schema,address)\");\n\n uint256 distributionIndex;\n bool found = false;\n for (uint256 i = 0; i < distributionTargets.length; ) {\n DistributionConfig storage config = distributionTargets[i];\n\n if (schema == config.schema && destination == config.destination && config.percentage == 0) {\n found = true;\n distributionIndex = i;\n break;\n }\n\n unchecked {\n ++i;\n }\n }\n\n if (found) {\n emit DistributionConfigRemoved(\n distributionTargets[distributionIndex].destination,\n distributionTargets[distributionIndex].percentage,\n distributionTargets[distributionIndex].schema\n );\n\n distributionTargets[distributionIndex] = distributionTargets[distributionTargets.length - 1];\n distributionTargets.pop();\n }\n\n _ensurePercentages();\n }\n\n /**\n * @dev Release funds\n * @param comptroller the comptroller address of the pool\n * @param assets assets to be released to distribution targets\n */\n function releaseFunds(address comptroller, address[] calldata assets) external nonReentrant {\n for (uint256 i = 0; i < assets.length; ) {\n _releaseFund(comptroller, assets[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Used to find out the amount of funds that's going to be released when release funds is called.\n * @param comptroller the comptroller address of the pool\n * @param schema the schema of the distribution target\n * @param destination the destination address of the distribution target\n * @param asset the asset address which will be released\n */\n function getUnreleasedFunds(\n address comptroller,\n Schema schema,\n address destination,\n address asset\n ) external view returns (uint256) {\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\n DistributionConfig storage _config = distributionTargets[i];\n if (_config.schema == schema && _config.destination == destination) {\n uint256 total = assetsReserves[comptroller][asset][schema];\n return (total * _config.percentage) / MAX_PERCENT;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Returns the total number of distribution targets\n */\n function totalDistributions() external view returns (uint256) {\n return distributionTargets.length;\n }\n\n /**\n * @dev Used to find out the percentage distribution for a particular destination based on schema\n * @param destination the destination address of the distribution target\n * @param schema the schema of the distribution target\n * @return percentage percentage distribution\n */\n function getPercentageDistribution(address destination, Schema schema) external view returns (uint256) {\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\n DistributionConfig memory config = distributionTargets[i];\n\n if (config.destination == destination && config.schema == schema) {\n return config.percentage;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\n * @param comptroller Comptroller address (pool)\n * @param asset Asset address.\n * @param incomeType type of income\n */\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) public override(IProtocolShareReserve) nonReentrant {\n if (!IComptroller(comptroller).isComptroller()) revert InvalidAddress();\n ensureNonzeroAddress(asset);\n\n if (\n comptroller != CORE_POOL_COMPTROLLER &&\n IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) == address(0)\n ) revert InvalidAddress();\n\n Schema schema = _getSchema(incomeType);\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\n uint256 assetReserve = totalAssetReserve[asset];\n\n if (currentBalance > assetReserve) {\n uint256 balanceDifference;\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n\n assetsReserves[comptroller][asset][schema] += balanceDifference;\n totalAssetReserve[asset] += balanceDifference;\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference, incomeType, schema);\n }\n }\n\n /**\n * @dev asset from a particular pool to be release to distribution targets\n * @param comptroller Comptroller address(pool)\n * @param asset Asset address.\n */\n function _releaseFund(address comptroller, address asset) internal {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint256[] memory schemaBalances = new uint256[](totalSchemas);\n uint256 totalBalance;\n for (uint256 schemaValue; schemaValue < totalSchemas; ) {\n schemaBalances[schemaValue] = assetsReserves[comptroller][asset][Schema(schemaValue)];\n totalBalance += schemaBalances[schemaValue];\n\n unchecked {\n ++schemaValue;\n }\n }\n\n if (totalBalance == 0) {\n return;\n }\n\n uint256[] memory totalTransferAmounts = new uint256[](totalSchemas);\n for (uint256 i = 0; i < distributionTargets.length; ) {\n DistributionConfig memory _config = distributionTargets[i];\n\n uint256 transferAmount = (schemaBalances[uint256(_config.schema)] * _config.percentage) / MAX_PERCENT;\n totalTransferAmounts[uint256(_config.schema)] += transferAmount;\n\n if (transferAmount != 0) {\n IERC20Upgradeable(asset).safeTransfer(_config.destination, transferAmount);\n IIncomeDestination(_config.destination).updateAssetsState(comptroller, asset);\n\n emit AssetReleased(_config.destination, asset, _config.schema, _config.percentage, transferAmount);\n }\n\n unchecked {\n ++i;\n }\n }\n\n uint256[] memory newSchemaBalances = new uint256[](totalSchemas);\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\n newSchemaBalances[schemaValue] = schemaBalances[schemaValue] - totalTransferAmounts[schemaValue];\n assetsReserves[comptroller][asset][Schema(schemaValue)] = newSchemaBalances[schemaValue];\n totalAssetReserve[asset] = totalAssetReserve[asset] - totalTransferAmounts[schemaValue];\n\n emit ReservesUpdated(\n comptroller,\n asset,\n Schema(schemaValue),\n schemaBalances[schemaValue],\n newSchemaBalances[schemaValue]\n );\n\n unchecked {\n ++schemaValue;\n }\n }\n }\n\n /**\n * @dev Returns the schema based on income type\n * @param incomeType type of income\n * @return schema schema for distribution\n */\n function _getSchema(IncomeType incomeType) internal view returns (Schema schema) {\n schema = Schema.ADDITIONAL_REVENUE;\n\n if (incomeType == IncomeType.SPREAD) {\n schema = Schema.PROTOCOL_RESERVES;\n }\n }\n\n /**\n * @dev This ensures that the total percentage of all the distribution targets is 100% or 0%\n */\n function _ensurePercentages() internal view {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint16[] memory totalPercentages = new uint16[](totalSchemas);\n\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\n DistributionConfig memory config = distributionTargets[i];\n totalPercentages[uint256(config.schema)] += config.percentage;\n\n unchecked {\n ++i;\n }\n }\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\n if (totalPercentages[schemaValue] != MAX_PERCENT && totalPercentages[schemaValue] != 0)\n revert InvalidTotalPercentage();\n\n unchecked {\n ++schemaValue;\n }\n }\n }\n\n /**\n * @dev Returns the underlying asset address for the vToken\n * @param vToken vToken address\n * @return asset address of asset\n */\n function _getUnderlying(address vToken) internal view returns (address) {\n if (vToken == vBNB) {\n return WBNB;\n } else {\n return IVToken(vToken).underlying();\n }\n }\n}\n" + }, + "contracts/ProtocolReserve/RiskFundStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\n\n/// @title ReserveHelpersStorage\n/// @author Venus\n/// @dev Reserve helpers storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract ReserveHelpersStorage is Ownable2StepUpgradeable {\n /// @notice Deprecated slot for assetReserves mapping\n bytes32 private __deprecatedSlot1;\n\n /// @notice Available asset's fund per pool in RiskFund\n /// Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) public poolAssetsFunds;\n\n /// @notice Deprecated slot for poolRegistry address\n bytes32 private __deprecatedSlot2;\n /// @notice Deprecated slot for status variable\n bytes32 private __deprecatedSlot3;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n uint256[46] private __gap;\n}\n\n/// @title MaxLoopsLimitHelpersStorage\n/// @author Venus\n/// @dev Max loop limit helpers storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract MaxLoopsLimitHelpersStorage {\n /// @notice Limit for the loops to avoid the DOS\n /// @notice This state is deprecated, using it to prevent storage collision\n uint256 public maxLoopsLimit;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n uint256[49] private __gap;\n}\n\n/// @title RiskFundV1Storage\n/// @author Venus\n/// @dev Risk fund V1 storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundV1Storage is ReserveHelpersStorage, MaxLoopsLimitHelpersStorage {\n /// @notice Address of base asset\n address public convertibleBaseAsset;\n /// @notice Address of shortfall contract\n address public shortfall;\n\n /// @notice This state is deprecated, using it to prevent storage collision\n address private pancakeSwapRouter;\n /// @notice This state is deprecated, using it to prevent storage collision\n uint256 private minAmountToConvert;\n}\n\n/// @title RiskFundV2Storage\n/// @author Venus\n/// @dev Risk fund V2 storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeable {\n /// @notice Risk fund converter address\n address public riskFundConverter;\n}\n" + }, + "contracts/ProtocolReserve/RiskFundV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IRiskFund } from \"../Interfaces/IRiskFund.sol\";\nimport { IRiskFundConverter } from \"../Interfaces/IRiskFundConverter.sol\";\nimport { RiskFundV2Storage } from \"./RiskFundStorage.sol\";\n\n/// @title RiskFundV2\n/// @author Venus\n/// @notice Contract with basic features to hold base asset for different Comptrollers\n/// @dev This contract does not support BNB\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Emitted when convertible base asset address is updated\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\n\n /// @notice Emitted when risk fund converter address is updated\n event RiskFundConverterUpdated(address indexed oldRiskFundConverter, address indexed newRiskFundConverter);\n\n /// @notice Emitted when shortfall contract address is updated\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\n\n /// @notice Emitted when reserves are transferred for auction\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\n\n /// @notice Emitted when pool asset states is updated with amount transferred to this contract\n event PoolAssetsIncreased(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\n event PoolAssetsDecreased(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Event emitted when tokens are swept\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /// @notice Event emitted when tokens are swept and transferred from pool\n event SweepTokenFromPool(address indexed token, address indexed comptroller, uint256 amount);\n\n /// @notice Error is thrown when updatePoolState is not called by riskFundConverter\n error InvalidRiskFundConverter();\n\n /// @notice Error is thrown when transferReserveForAuction is called by non shortfall address\n error InvalidShortfallAddress();\n\n /// @notice thrown when amount entered is greater than balance\n error InsufficientBalance();\n\n /// @notice Error is thrown when pool reserve is less than the amount needed\n error InsufficientPoolReserve(address comptroller, uint256 amount, uint256 poolReserve);\n\n /// @dev Convertible base asset setter\n /// @param convertibleBaseAsset_ Address of the convertible base asset\n /// @custom:event ConvertibleBaseAssetUpdated emit on success\n /// @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n /// @custom:access Only Governance\n function setConvertibleBaseAsset(address convertibleBaseAsset_) external onlyOwner {\n ensureNonzeroAddress(convertibleBaseAsset_);\n emit ConvertibleBaseAssetUpdated(convertibleBaseAsset, convertibleBaseAsset_);\n convertibleBaseAsset = convertibleBaseAsset_;\n }\n\n /// @dev Risk fund converter setter\n /// @param riskFundConverter_ Address of the risk fund converter\n /// @custom:event RiskFundConverterUpdated emit on success\n /// @custom:error ZeroAddressNotAllowed is thrown when risk fund converter address is zero\n /// @custom:access Only Governance\n function setRiskFundConverter(address riskFundConverter_) external onlyOwner {\n ensureNonzeroAddress(riskFundConverter_);\n emit RiskFundConverterUpdated(riskFundConverter, riskFundConverter_);\n riskFundConverter = riskFundConverter_;\n }\n\n /// @dev Shortfall contract address setter\n /// @param shortfallContractAddress_ Address of the auction contract\n /// @custom:event ShortfallContractUpdated emit on success\n /// @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n /// @custom:access Only Governance\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\n ensureNonzeroAddress(shortfallContractAddress_);\n emit ShortfallContractUpdated(shortfall, shortfallContractAddress_);\n shortfall = shortfallContractAddress_;\n }\n\n /// @dev Transfer tokens for auction to shortfall contract\n /// @param comptroller Comptroller of the pool\n /// @param amount Amount to be transferred to the shortfall\n /// @return Amount of tokens transferred to the shortfall\n /// @custom:event TransferredReserveForAuction emit on success\n /// @custom:error InvalidShortfallAddress is thrown when caller is not shortfall contract\n /// @custom:error InsufficientPoolReserve is thrown when pool reserve is less than the amount needed\n /// @custom:access Only Shortfall contract\n function transferReserveForAuction(address comptroller, uint256 amount)\n external\n override\n nonReentrant\n returns (uint256)\n {\n uint256 poolReserve = poolAssetsFunds[comptroller][convertibleBaseAsset];\n\n if (msg.sender != shortfall) {\n revert InvalidShortfallAddress();\n }\n if (amount > poolReserve) {\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\n }\n\n unchecked {\n poolAssetsFunds[comptroller][convertibleBaseAsset] = poolReserve - amount;\n }\n\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall, amount);\n emit TransferredReserveForAuction(comptroller, amount);\n\n return amount;\n }\n\n /// @notice Function to sweep baseAsset for pool, Tokens are sent to address(to)\n /// @param tokenAddress Address of the asset(token)\n /// @param to Address to which assets will be transferred\n /// @param amount Amount need to sweep for the pool\n /// @custom:event Emits SweepToken event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\n /// @custom:access Only Governance\n function sweepToken(\n address tokenAddress,\n address to,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(to);\n ensureNonzeroValue(amount);\n\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n preSweepToken(tokenAddress, amount);\n token.safeTransfer(to, amount);\n\n emit SweepToken(tokenAddress, to, amount);\n }\n\n /// @notice Function to sweep token from pool\n /// @param tokenAddress Address of the asset(token)\n /// @param comptroller Pool address to which assets will be transferred\n /// @param amount Amount need to sweep from the pool\n /// @custom:event Emits sweepTokenFromPool event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zero\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\n /// @custom:access Only Governance\n function sweepTokenFromPool(\n address tokenAddress,\n address comptroller,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(comptroller);\n ensureNonzeroValue(amount);\n\n uint256 poolReserve = poolAssetsFunds[comptroller][tokenAddress];\n\n if (amount > poolReserve) {\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\n }\n\n unchecked {\n poolAssetsFunds[comptroller][tokenAddress] = poolReserve - amount;\n }\n\n IERC20Upgradeable(tokenAddress).safeTransfer(comptroller, amount);\n\n emit SweepTokenFromPool(tokenAddress, comptroller, amount);\n }\n\n /**\n * @notice Get the Amount of the Base asset in the risk fund for the specific pool.\n * @param comptroller Comptroller address(pool).\n * @return Base Asset's reserve in risk fund.\n */\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256) {\n return poolAssetsFunds[comptroller][convertibleBaseAsset];\n }\n\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\n /// @param comptroller Comptroller address (pool)\n /// @param asset Address of the asset(token)\n /// @param amount Amount transferred for the pool\n /// @custom:event PoolAssetsIncreased emits on success\n /// @custom:error InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\n /// @custom:access Only RiskFundConverter contract\n function updatePoolState(\n address comptroller,\n address asset,\n uint256 amount\n ) public {\n if (msg.sender != riskFundConverter) {\n revert InvalidRiskFundConverter();\n }\n\n poolAssetsFunds[comptroller][asset] += amount;\n emit PoolAssetsIncreased(comptroller, asset, amount);\n }\n\n /// @dev Operations to perform before sweeping tokens\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\n function preSweepToken(address tokenAddress, uint256 amount) internal {\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\n if (amount > balance) revert InsufficientBalance();\n\n address[] memory pools = IRiskFundConverter(riskFundConverter).getPools(tokenAddress);\n\n uint256 assetReserves;\n uint256 poolsLength = pools.length;\n for (uint256 i; i < poolsLength; ) {\n assetReserves += poolAssetsFunds[pools[i]][tokenAddress];\n unchecked {\n ++i;\n }\n }\n\n uint256 balanceDiff = balance - assetReserves;\n\n if (balanceDiff < amount) {\n uint256 amountDiff;\n unchecked {\n amountDiff = amount - balanceDiff;\n }\n uint256 distributedShare;\n for (uint256 i; i < poolsLength; ) {\n if (poolAssetsFunds[pools[i]][tokenAddress] != 0) {\n uint256 poolAmountShare;\n if (i < (poolsLength - 1)) {\n poolAmountShare = (poolAssetsFunds[pools[i]][tokenAddress] * amount) / assetReserves;\n distributedShare += poolAmountShare;\n } else {\n poolAmountShare = amountDiff - distributedShare;\n }\n poolAssetsFunds[pools[i]][tokenAddress] -= poolAmountShare;\n emit PoolAssetsDecreased(pools[i], tokenAddress, poolAmountShare);\n }\n unchecked {\n ++i;\n }\n }\n }\n }\n}\n" + }, + "contracts/ProtocolReserve/XVSVaultTreasury.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IXVSVault } from \"../Interfaces/IXVSVault.sol\";\n\n/// @title XVSVaultTreasury\n/// @author Venus\n/// @notice XVSVaultTreasury stores the tokens sent by SingleTokenConverter(XVS) and funds XVSVault\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract XVSVaultTreasury is AccessControlledV8, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The xvs token address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable XVS_ADDRESS;\n\n /// @notice The xvsvault address\n address public xvsVault;\n\n /// @notice Emitted when XVS vault address is updated\n event XVSVaultUpdated(address indexed oldXVSVault, address indexed newXVSVault);\n\n /// @notice Emitted when funds transferred to XVSStore address\n event FundsTransferredToXVSStore(address indexed xvsStore, uint256 amountMantissa);\n\n /// @notice Thrown when given input amount is zero\n error InsufficientBalance();\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @param xvsAddress_ XVS token address\n constructor(address xvsAddress_) {\n ensureNonzeroAddress(xvsAddress_);\n XVS_ADDRESS = xvsAddress_;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param xvsVault_ XVSVault address\n /// @custom:event XVSVaultUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when XVS vault address is zero\n function initialize(address accessControlManager_, address xvsVault_) public initializer {\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n _setXVSVault(xvsVault_);\n }\n\n /// @dev XVS vault setter\n /// @param xvsVault_ Address of the XVS vault\n /// @custom:event XVSVaultUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when XVS vault address is zero\n function setXVSVault(address xvsVault_) external onlyOwner {\n _setXVSVault(xvsVault_);\n }\n\n /// @notice This function transfers funds to the XVS vault\n /// @param amountMantissa Amount to be sent to XVS vault\n /// @custom:event FundsTransferredToXVSStore emits on success\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\n /// @custom:access Restricted by ACM\n function fundXVSVault(uint256 amountMantissa) external nonReentrant {\n _checkAccessAllowed(\"fundXVSVault(uint256)\");\n ensureNonzeroValue(amountMantissa);\n\n uint256 balance = IERC20Upgradeable(XVS_ADDRESS).balanceOf(address(this));\n\n if (balance < amountMantissa) {\n revert InsufficientBalance();\n }\n\n address xvsStore = IXVSVault(xvsVault).xvsStore();\n ensureNonzeroAddress(xvsStore);\n IERC20Upgradeable(XVS_ADDRESS).safeTransfer(xvsStore, amountMantissa);\n\n emit FundsTransferredToXVSStore(xvsStore, amountMantissa);\n }\n\n /// @dev XVS vault setter\n /// @param xvsVault_ Address of the XVS vault\n /// @custom:event XVSVaultUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when XVS vault address is zero\n function _setXVSVault(address xvsVault_) internal {\n ensureNonzeroAddress(xvsVault_);\n emit XVSVaultUpdated(xvsVault, xvsVault_);\n xvsVault = xvsVault_;\n }\n}\n" + }, + "contracts/Test/imports.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n// This file is needed to make hardhat and typechain generate artifacts for\n// contracts we depend on (e.g. in tests or deployments) but not use directly.\n// Another way to do this would be to use hardhat-dependency-compiler, but\n// since we only have a couple of dependencies, installing a separate package\n// seems an overhead.\n\nimport { UpgradeableBeacon } from \"@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol\";\nimport { BeaconProxy } from \"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\";\n" + }, + "contracts/Test/Mocks/MockACM.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { AccessControl } from \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract MockACM is AccessControl {\n /// @notice Emitted when an account is given a permission to a certain contract function\n /// @dev If contract address is 0x000..0 this means that the account is a default admin of this function and\n /// can call any contract function with this signature\n event PermissionGranted(address account, address contractAddress, string functionSig);\n\n /// @notice Emitted when an account is revoked a permission to a certain contract function\n event PermissionRevoked(address account, address contractAddress, string functionSig);\n\n constructor() {\n // Grant the contract deployer the default admin role: it will be able\n // to grant and revoke any roles\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Gives a function call permission to one single account\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n * @param contractAddress address of contract for which call permissions will be granted\n * @dev if contractAddress is zero address, the account can access the specified function\n * on **any** contract managed by this ACL\n * @param functionSig signature e.g. \"functionName(uint256,bool)\"\n * @param accountToPermit account that will be given access to the contract function\n * @custom:event Emits a {RoleGranted} and {PermissionGranted} events.\n */\n function giveCallPermission(\n address contractAddress,\n string memory functionSig,\n address accountToPermit\n ) public {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n grantRole(role, accountToPermit);\n emit PermissionGranted(accountToPermit, contractAddress, functionSig);\n }\n\n /**\n * @notice Revokes an account's permission to a particular function call\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n * \t\tMay emit a {RoleRevoked} event.\n * @param contractAddress address of contract for which call permissions will be revoked\n * @param functionSig signature e.g. \"functionName(uint256,bool)\"\n * @custom:event Emits {RoleRevoked} and {PermissionRevoked} events.\n */\n function revokeCallPermission(\n address contractAddress,\n string memory functionSig,\n address accountToRevoke\n ) public {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n revokeRole(role, accountToRevoke);\n emit PermissionRevoked(accountToRevoke, contractAddress, functionSig);\n }\n\n /**\n * @notice Verifies if the given account can call a contract's guarded function\n * @dev Since restricted contracts using this function as a permission hook, we can get contracts address with msg.sender\n * @param account for which call permissions will be checked\n * @param functionSig restricted function signature e.g. \"functionName(uint256,bool)\"\n * @return false if the user account cannot call the particular contract function\n *\n */\n function isAllowedToCall(address account, string memory functionSig) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(msg.sender, functionSig));\n\n if (hasRole(role, account)) {\n return true;\n } else {\n role = keccak256(abi.encodePacked(address(0), functionSig));\n return hasRole(role, account);\n }\n }\n\n /**\n * @notice Verifies if the given account can call a contract's guarded function\n * @dev This function is used as a view function to check permissions rather than contract hook for access restriction check.\n * @param account for which call permissions will be checked against\n * @param contractAddress address of the restricted contract\n * @param functionSig signature of the restricted function e.g. \"functionName(uint256,bool)\"\n * @return false if the user account cannot call the particular contract function\n */\n function hasPermission(\n address account,\n address contractAddress,\n string memory functionSig\n ) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n return hasRole(role, account);\n }\n}\n" + }, + "contracts/Test/Mocks/MockArraySorter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\nimport { sort } from \"../../Utils/ArrayHelpers.sol\";\n\ncontract MockArraySorter {\n function sortArray(uint256[] memory balances, address[] memory addrs)\n external\n view\n returns (address[] memory, uint256[] memory)\n {\n sort(balances, addrs);\n return (addrs, balances);\n }\n}\n" + }, + "contracts/Test/Mocks/MockConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\n\nimport { AbstractTokenConverter } from \"../../TokenConverter/AbstractTokenConverter.sol\";\nimport { IRiskFundGetters } from \"../../Interfaces/IRiskFund.sol\";\n\ncontract MockConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) public assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) public poolsAssetsReserves;\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n function mockPrivateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 balanceDiff\n ) external {\n _privateConversion(comptroller, tokenAddressOut, balanceDiff);\n }\n\n function AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) public initializer {\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n assetsReserves[tokenAddressIn] += convertedTokenInBalance;\n poolsAssetsReserves[comptroller][tokenAddressIn] += convertedTokenInBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @notice Get base asset address\n function _getDestinationBaseAsset() internal view override returns (address) {\n return IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/Test/Mocks/MockDeflationaryToken.sol": { + "content": "pragma solidity 0.8.13;\n\ncontract MockDeflatingToken {\n string public constant NAME = \"Deflating Test Token\";\n string public constant SYMBOL = \"DTT\";\n uint8 public constant DECIMALS = 18;\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n mapping(address => mapping(address => uint256)) public allowance;\n\n bytes32 public immutable DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n event Approval(address indexed owner, address indexed spender, uint256 value);\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n constructor(uint256 _totalSupply) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string NAME,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(NAME)),\n keccak256(bytes(\"1\")),\n chainId,\n address(this)\n )\n );\n _mint(msg.sender, _totalSupply);\n }\n\n function approve(address spender, uint256 value) external returns (bool) {\n _approve(msg.sender, spender, value);\n return true;\n }\n\n function transfer(address to, uint256 value) external returns (bool) {\n _transfer(msg.sender, to, value);\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n ) external returns (bool) {\n if (allowance[from][msg.sender] != type(uint256).max) {\n allowance[from][msg.sender] = allowance[from][msg.sender] - value;\n }\n _transfer(from, to, value);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"EXPIRED\");\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNATURE\");\n _approve(owner, spender, value);\n }\n\n function _mint(address to, uint256 value) internal {\n totalSupply = totalSupply + value;\n balanceOf[to] = balanceOf[to] + value;\n emit Transfer(address(0), to, value);\n }\n\n function _burn(address from, uint256 value) internal {\n balanceOf[from] = balanceOf[from] - value;\n totalSupply = totalSupply - value;\n emit Transfer(from, address(0), value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n ) private {\n allowance[owner][spender] = value;\n emit Approval(owner, spender, value);\n }\n\n function _transfer(\n address from,\n address to,\n uint256 value\n ) private {\n uint256 burnAmount = value / 100;\n _burn(from, burnAmount);\n uint256 transferAmount = value - burnAmount;\n balanceOf[from] = balanceOf[from] - transferAmount;\n balanceOf[to] = balanceOf[to] + transferAmount;\n emit Transfer(from, to, transferAmount);\n }\n}\n" + }, + "contracts/Test/Mocks/MockRiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { RiskFundConverter } from \"../../TokenConverter/RiskFundConverter.sol\";\n\ncontract MockRiskFundConverter is RiskFundConverter {\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) RiskFundConverter(corePoolComptroller_, vBNB_, nativeWrapped_) {}\n\n function postConversionHookMock(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) external {\n super._postConversionHook(tokenInAddress, tokenOutAddress, amountIn, amountOut);\n }\n\n function preTransferHookMock(address tokenOutAddress, uint256 amountOut) external {\n super._preTransferHook(tokenOutAddress, amountOut);\n }\n\n function setAssetsReserves(address asset, uint256 amount) external {\n assetsReserves[asset] = amount;\n }\n\n function setPoolsAssetsReserves(\n address comptroller,\n address asset,\n uint256 amount\n ) external {\n poolsAssetsReserves[comptroller][asset] = amount;\n }\n\n function getPoolsAssetsReserves(address comptroller, address asset) external view returns (uint256) {\n return poolsAssetsReserves[comptroller][asset];\n }\n\n function getAssetsReserves(address asset) external view returns (uint256) {\n return assetsReserves[asset];\n }\n}\n" + }, + "contracts/Test/Mocks/MockToken.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 { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockToken is ERC20 {\n uint8 private immutable _decimals;\n\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) ERC20(name_, symbol_) {\n _decimals = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function allocateTo(address owner, uint256 amount) external {\n _mint(owner, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/TokenConverter/AbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { MANTISSA_ONE, EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\nimport { IAbstractTokenConverter } from \"./IAbstractTokenConverter.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @title AbstractTokenConverter\n/// @author Venus\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\n/*\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\n *\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\n * a. convertExactTokensSupportingFeeOnTransferTokens\n * b. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\n * similar to Case I.\n *\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * a. convertExactTokens\n * b. convertForExactTokens\n * c. convertExactTokensSupportingFeeOnTransferTokens\n * d. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * similar to Case III.\n *\n * ------------------------------------------------------------------------------------------------------------------------------------\n * Example 1:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInAmount - 100\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\n * function for tokenIn as deflationary token.\n *\n * Example 2:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\n * tokenOutAmount - 70\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\n * ------------------------------------------------------------------------------------------------------------------------------------\n *\n * This contract also supports private conversion between the converters:\n * Private conversions:\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\n *\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\n *\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\n * tokenAddressOut: As base asset of that converter.\n *\n * ConverterNetwork:\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\n * and tokenAddressOut provided.\n *\n * findTokenConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\n *\n * findTokenConvertersForConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\n */\n\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Maximum incentive could be\n uint256 public constant MAX_INCENTIVE = 0.5e18;\n\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\n uint256 public minAmountToConvert;\n\n /// @notice Venus price oracle contract\n ResilientOracle public priceOracle;\n\n /// @notice conversion configurations for the existing pairs\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\n\n /// @notice Address that all incoming tokens are transferred to\n address public destinationAddress;\n\n /// @notice Boolean for if conversion is paused\n bool public conversionPaused;\n\n /// @notice Address of the converterNetwork contract\n IConverterNetwork public converterNetwork;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n uint256[45] private __gap;\n\n /// @notice Emitted when config is updated for tokens pair\n event ConversionConfigUpdated(\n address indexed tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 oldIncentive,\n uint256 newIncentive,\n ConversionAccessibility oldAccess,\n ConversionAccessibility newAccess\n );\n /// @notice Emitted when price oracle address is updated\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\n\n /// @notice Emitted when destination address is updated\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\n\n /// @notice Emitted when converterNetwork address is updated\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\n\n /// @notice Emitted when exact amount of tokens are converted for tokens\n event ConvertedExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens\n event ConvertedForExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when conversion is paused\n event ConversionPaused(address indexed sender);\n\n /// @notice Emitted when conversion is unpaused\n event ConversionResumed(address indexed sender);\n\n /// @notice Event emitted when tokens are swept\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\n error AmountOutMismatched();\n\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\n error AmountInMismatched();\n\n /// @notice Thrown when given input amount is zero\n error InsufficientInputAmount();\n\n /// @notice Thrown when given output amount is zero\n error InsufficientOutputAmount();\n\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\n error ConversionConfigNotEnabled();\n\n /// @notice Thrown when conversion is enabled only for private conversions\n error ConversionEnabledOnlyForPrivateConversions();\n\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n error InvalidToAddress();\n\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\n\n /// @notice Thrown when amountOut is lower than amountOutMin\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\n\n /// @notice Thrown when amountIn is higher than amountInMax\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\n\n /// @notice Thrown when conversion is paused\n error ConversionTokensPaused();\n\n /// @notice Thrown when conversion is Active\n error ConversionTokensActive();\n\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\n error InvalidTokenConfigAddresses();\n\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\n error InsufficientPoolLiquidity();\n\n /// @notice When address of the ConverterNetwork is not set or Zero address\n error InvalidConverterNetwork();\n\n /// @notice Thrown when trying to set non zero incentive for private conversion\n error NonZeroIncentiveForPrivateConversion();\n\n /// @notice Thrown when using convertForExactTokens deflationary tokens\n error DeflationaryTokenNotSupported();\n\n /// @notice Thrown when minimum amount to convert is zero\n error InvalidMinimumAmountToConvert();\n\n /// @notice Thrown when there is a mismatch in the length of input arrays\n error InputLengthMisMatch();\n\n /**\n * @notice Modifier to ensure valid conversion parameters for a token conversion\n * and check if conversion is paused or not\n * @param to The recipient address for the converted tokens\n * @param tokenAddressIn The input token address for the conversion\n * @param tokenAddressOut The output token address for the conversion\n */\n modifier validConversionParameters(\n address to,\n address tokenAddressIn,\n address tokenAddressOut\n ) {\n _checkConversionPaused();\n ensureNonzeroAddress(to);\n if (to == tokenAddressIn || to == tokenAddressOut) {\n revert InvalidToAddress();\n }\n _;\n }\n\n /// @notice Pause conversion of tokens\n /// @custom:event Emits ConversionPaused on success\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\n /// @custom:access Restricted by ACM\n function pauseConversion() external {\n _checkAccessAllowed(\"pauseConversion()\");\n _checkConversionPaused();\n conversionPaused = true;\n emit ConversionPaused(msg.sender);\n }\n\n /// @notice Resume conversion of tokens.\n /// @custom:event Emits ConversionResumed on success\n /// @custom:error ConversionTokensActive thrown when conversion is already active\n /// @custom:access Restricted by ACM\n function resumeConversion() external {\n _checkAccessAllowed(\"resumeConversion()\");\n if (!conversionPaused) {\n revert ConversionTokensActive();\n }\n\n conversionPaused = false;\n emit ConversionResumed(msg.sender);\n }\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:access Only Governance\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\n _setPriceOracle(priceOracle_);\n }\n\n /// @notice Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:access Only Governance\n function setDestination(address destinationAddress_) external onlyOwner {\n _setDestination(destinationAddress_);\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:access Only Governance\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\n _setConverterNetwork(converterNetwork_);\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:access Only Governance\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n _setMinAmountToConvert(minAmountToConvert_);\n }\n\n /// @notice Batch sets the conversion configurations\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressesOut Array of addresses of tokenOut\n /// @param conversionConfigs Array of conversionConfig config details to update\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\n function setConversionConfigs(\n address tokenAddressIn,\n address[] calldata tokenAddressesOut,\n ConversionConfig[] calldata conversionConfigs\n ) external {\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\n\n for (uint256 i; i < tokenOutArrayLength; ) {\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountIn != amountInMantissa) {\n revert AmountInMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\n /// otherwise the amount is adjusted\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountOut != amountOutMantissa) {\n revert AmountOutMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\n /// @param tokenAddress The address of the ERC-20 token to sweep\n /// @param to The address to which tokens will be transferred\n /// @param amount The amount to transfer\n /// @custom:event Emits SweepToken event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\n /// @custom:access Only Governance\n function sweepToken(\n address tokenAddress,\n address to,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(to);\n ensureNonzeroValue(amount);\n\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n preSweepToken(tokenAddress, amount);\n token.safeTransfer(to, amount);\n\n emit SweepToken(tokenAddress, to, amount);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @dev This function retrieves values without altering token prices\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n amountConvertedMantissa = amountInMantissa;\n uint256 tokenInToOutConversion;\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountConvertedMantissa =\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\n tokenInToOutConversion; //round-up\n amountOutMantissa = maxTokenOutReserve;\n }\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @dev This function retrieves values without altering token prices\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountOutMantissa = maxTokenOutReserve;\n }\n\n amountConvertedMantissa = amountOutMantissa;\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountInMantissa;\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountOutMantissa;\n }\n\n /// @notice This method updated the states of this contract after getting funds from PSR\n /// after settling the amount(if any) through privateConversion between converters\n /// @dev This function is called by protocolShareReserve\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\n if (balanceDiff > 0) {\n _privateConversion(comptroller, asset, balanceDiff);\n }\n }\n\n /// @notice Set the configuration for new or existing conversion pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n /// @custom:event Emits ConversionConfigUpdated event on success\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\n /// @custom:access Controlled by AccessControlManager\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) public {\n _checkAccessAllowed(\"setConversionConfig(address,address,ConversionConfig)\");\n ensureNonzeroAddress(tokenAddressIn);\n ensureNonzeroAddress(tokenAddressOut);\n\n if (conversionConfig.incentive > MAX_INCENTIVE) {\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\n }\n\n if (\n (tokenAddressIn == tokenAddressOut) ||\n (tokenAddressIn != _getDestinationBaseAsset()) ||\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\n ) {\n revert InvalidTokenConfigAddresses();\n }\n\n if (\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\n conversionConfig.incentive != 0\n ) {\n revert NonZeroIncentiveForPrivateConversion();\n }\n\n if (\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\n (address(converterNetwork) == address(0))\n ) {\n revert InvalidConverterNetwork();\n }\n\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n emit ConversionConfigUpdated(\n tokenAddressIn,\n tokenAddressOut,\n configuration.incentive,\n conversionConfig.incentive,\n configuration.conversionAccess,\n conversionConfig.conversionAccess\n );\n\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\n } else {\n configuration.incentive = conversionConfig.incentive;\n configuration.conversionAccess = conversionConfig.conversionAccess;\n }\n }\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\n\n /// @dev Operations to perform before sweeping tokens\n /// @param token Address of the token\n /// @param amount Amount transferred to address(to)\n function preSweepToken(address token, uint256 amount) internal virtual {}\n\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function _convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n if (amountOutMantissa < amountOutMinMantissa) {\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n }\n\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\n /// it is called by convertForExactTokens function\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n if (actualAmountIn != amountInMantissa) {\n revert DeflationaryTokenNotSupported();\n }\n\n if (actualAmountIn > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n actualAmountOut = amountOutMantissa;\n }\n\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n if (amountInMantissa > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\n }\n\n /// @dev return actualAmountOut from reserves for tokenAddressOut\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\n function _doTransferOut(\n address tokenAddressOut,\n address to,\n uint256 amountConvertedMantissa\n ) internal {\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountConvertedMantissa) {\n revert InsufficientPoolLiquidity();\n }\n\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\n\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\n tokenOut.safeTransfer(to, amountConvertedMantissa);\n }\n\n /// @notice Transfer tokenAddressIn from user to destination\n /// @param tokenAddressIn Address of the token to convert\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @return actualAmountIn Actual amount transferred to destination\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\n }\n\n /// @dev Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:event Emits PriceOracleUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\n ensureNonzeroAddress(address(priceOracle_));\n emit PriceOracleUpdated(priceOracle, priceOracle_);\n priceOracle = priceOracle_;\n }\n\n /// @dev Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:event Emits DestinationAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\n function _setDestination(address destinationAddress_) internal {\n ensureNonzeroAddress(destinationAddress_);\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\n destinationAddress = destinationAddress_;\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\n ensureNonzeroAddress(address(converterNetwork_));\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\n converterNetwork = converterNetwork_;\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:event MinAmountToConvertUpdated is emitted in success\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\n ensureNonzeroValue(minAmountToConvert_);\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\n minAmountToConvert = minAmountToConvert_;\n }\n\n /// @dev Hook to perform after converting tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param amountIn Amount of tokenIn converted\n /// @param amountOut Amount of tokenOut converted\n function _postConversionHook(\n address tokenAddressIn,\n address tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n ) internal virtual {}\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init_unchained(\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n _setPriceOracle(priceOracle_);\n _setDestination(destinationAddress_);\n _setMinAmountToConvert(minAmountToConvert_);\n conversionPaused = false;\n }\n\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return Amount of asset, for _privateConversion\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\n\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\n /// destination contract as destination's base asset\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\n function _privateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 amountToConvert\n ) internal {\n address tokenAddressIn = _getDestinationBaseAsset();\n address _destinationAddress = destinationAddress;\n uint256 convertedTokenInBalance;\n if (address(converterNetwork) != address(0)) {\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\n uint256 convertersLength = converterAddresses.length;\n for (uint256 i; i < convertersLength; ) {\n if (converterBalances[i] == 0) break;\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\n converterBalances[i],\n tokenAddressOut,\n tokenAddressIn\n );\n if (amountIn > amountToConvert) {\n amountIn = amountToConvert;\n }\n\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\n break;\n }\n\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\n amountIn,\n 0,\n tokenAddressOut,\n tokenAddressIn,\n _destinationAddress\n );\n\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n amountToConvert -= amountIn;\n convertedTokenInBalance += (balanceAfter - balanceBefore);\n\n if (amountToConvert == 0) break;\n unchecked {\n ++i;\n }\n }\n }\n\n _postPrivateConversionHook(\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance,\n tokenAddressOut,\n amountToConvert\n );\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal virtual {}\n\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\n\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\n /// @param amountIn The amount to convert\n /// @param tokenAddress Address of the token\n /// @return isValid true if amount to convert is greater than minimum amount to convert\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\n priceOracle.updateAssetPrice(tokenAddress);\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\n\n if (amountInInUsd >= minAmountToConvert) {\n isValid = true;\n }\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\n if (amountInMantissa == 0) {\n revert InsufficientInputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\n /// multiplied by conversionWithIncentive which will be >= 1\n amountOutMantissa =\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\n (tokenOutUnderlyingPrice * EXP_SCALE);\n\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n }\n\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\n if (amountOutMantissa == 0) {\n revert InsufficientOutputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\n }\n\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\n if (\n (!(isConverter) &&\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n }\n\n /// @dev To check, is conversion paused\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\n function _checkConversionPaused() internal view {\n if (conversionPaused) {\n revert ConversionTokensPaused();\n }\n }\n\n /// @dev Get base asset address of the destination contract\n /// @return Address of the base asset\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\n}\n" + }, + "contracts/TokenConverter/ConverterNetwork.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { sort } from \"../Utils/ArrayHelpers.sol\";\nimport { IAbstractTokenConverter } from \"./IAbstractTokenConverter.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @title ConverterNetwork\n/// @author Venus\n/// @notice ConverterNetwork keeps track of all the converters and is used to fetch valid converters which provide conversions according to token addresses provided\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract ConverterNetwork is IConverterNetwork, AccessControlledV8, MaxLoopsLimitHelper {\n /// @notice Array holding all the converters\n IAbstractTokenConverter[] public allConverters;\n\n /// @notice Emitted when new converter is added\n event ConverterAdded(address indexed converter);\n\n /// @notice Emitted when converter is removed\n event ConverterRemoved(address indexed converter);\n\n /// @notice Error thrown when converter already exists\n error ConverterAlreadyExists();\n\n /// @notice Error thrown converter does not exist\n error ConverterDoesNotExist();\n\n /// @notice Error thrown when converter address is invalid\n error InvalidTokenConverterAddress();\n\n /// @notice Error thrown when loops limit is invalid\n error InvalidMaxLoopsLimit(uint256 loopsLimit);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @notice ConverterNetwork initializer\n /// @param _accessControlManager The address of ACM contract\n /// @param _loopsLimit Limit for the loops in the contract to avoid DOS\n /// @custom:event ConverterAdded is emitted for each converter added on success\n /// @custom:error InvalidMaxLoopsLimit is thrown when when loops limit is invalid\n function initialize(address _accessControlManager, uint256 _loopsLimit) external initializer {\n ensureNonzeroAddress(_accessControlManager);\n __AccessControlled_init(_accessControlManager);\n\n if (_loopsLimit >= type(uint128).max) revert InvalidMaxLoopsLimit(_loopsLimit);\n _setMaxLoopsLimit(_loopsLimit);\n }\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param limit Limit for the max loops can execute at a time\n * @custom:error InvalidMaxLoopsLimit is thrown when when loops limit is invalid\n * @custom:access Only owner\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n if (limit >= type(uint128).max) revert InvalidMaxLoopsLimit(limit);\n _setMaxLoopsLimit(limit);\n }\n\n /// @notice Adds new converter to the array\n /// @param _tokenConverter Address of the token converter\n /// @custom:event ConverterAdded is emitted on success\n /// @custom:access Only Governance\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external {\n _checkAccessAllowed(\"addTokenConverter(address)\");\n _addTokenConverter(_tokenConverter);\n }\n\n /// @notice Removes converter from the array\n /// @param _tokenConverter Address of the token converter\n /// @custom:error ConverterDoesNotExist is thrown when converter to remove does not exist\n /// @custom:event ConverterRemoved is emitted on success\n /// @custom:access Only Governance\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external {\n _checkAccessAllowed(\"removeTokenConverter(address)\");\n\n // Find the index of the converter in the array\n uint128 indexToRemove = _findConverterIndex(_tokenConverter);\n\n // Ensure that the converter exists in the array\n if (indexToRemove == type(uint128).max) revert ConverterDoesNotExist();\n\n // Swap the element to remove with the last element\n allConverters[indexToRemove] = allConverters[allConverters.length - 1];\n\n // Remove the last element (which is now a duplicate)\n allConverters.pop();\n\n emit ConverterRemoved(address(_tokenConverter));\n }\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// It will return the converters which are open to users for conversion\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance)\n {\n (converters, convertersBalance) = _findTokenConverters(_tokenAddressIn, _tokenAddressOut, false);\n }\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// It will return the converters which are open to converters for conversion.\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance)\n {\n (converters, convertersBalance) = _findTokenConverters(_tokenAddressIn, _tokenAddressOut, true);\n }\n\n /// @notice This function returns the array containing all the converters addresses\n /// @return converters Array containing all the converters addresses\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory converters) {\n converters = allConverters;\n }\n\n /// @notice This function checks if the given address is a converter or not\n /// @param _tokenConverter Address of the token converter\n /// @return isConverter true if given address is converter otherwise false\n function isTokenConverter(address _tokenConverter) external view returns (bool isConverter) {\n uint128 index = _findConverterIndex(IAbstractTokenConverter(_tokenConverter));\n\n if (index != type(uint128).max) {\n isConverter = true;\n }\n }\n\n /// @notice Adds new converter contract to the array\n /// @param _tokenConverter Address of the token converter\n /// @custom:error ConverterAlreadyExists is thrown when new tokenconverter to add already exists\n /// @custom:event ConverterAdded is emitted on success\n function _addTokenConverter(IAbstractTokenConverter _tokenConverter) internal {\n if (\n (address(_tokenConverter) == address(0)) || (address(_tokenConverter.converterNetwork()) != address(this))\n ) {\n revert InvalidTokenConverterAddress();\n }\n\n uint128 index = _findConverterIndex(_tokenConverter);\n if (index != type(uint128).max) revert ConverterAlreadyExists();\n\n allConverters.push(_tokenConverter);\n _ensureMaxLoops(allConverters.length);\n\n emit ConverterAdded(address(_tokenConverter));\n }\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @param forConverters Bool to filter out converters on the basis of the conversionAccess\n /// @return converters Array of converters\n /// @return convertersBalance Array of balances with respect to token out\n function _findTokenConverters(\n address _tokenAddressIn,\n address _tokenAddressOut,\n bool forConverters\n ) internal returns (address[] memory converters, uint256[] memory convertersBalance) {\n uint128 convertersLength = uint128(allConverters.length);\n\n // Create a dynamic array to store the matching converters\n converters = new address[](convertersLength);\n convertersBalance = new uint256[](convertersLength);\n uint128 count;\n\n for (uint128 i; i < convertersLength; ) {\n IAbstractTokenConverter converter = allConverters[i];\n\n unchecked {\n ++i;\n }\n\n if ((address(converter.converterNetwork()) != address(this)) || msg.sender == address(converter)) {\n continue;\n }\n\n (, IAbstractTokenConverter.ConversionAccessibility conversionAccess) = converter.conversionConfigurations(\n _tokenAddressIn,\n _tokenAddressOut\n );\n\n if (conversionAccess == IAbstractTokenConverter.ConversionAccessibility.ALL) {\n converters[count] = address(converter);\n convertersBalance[count] = converter.balanceOf(_tokenAddressOut);\n ++count;\n } else if (\n forConverters &&\n (conversionAccess == IAbstractTokenConverter.ConversionAccessibility.ONLY_FOR_CONVERTERS)\n ) {\n converters[count] = address(converter);\n convertersBalance[count] = converter.balanceOf(_tokenAddressOut);\n ++count;\n } else if (\n !forConverters && (conversionAccess == IAbstractTokenConverter.ConversionAccessibility.ONLY_FOR_USERS)\n ) {\n converters[count] = address(converter);\n convertersBalance[count] = converter.balanceOf(_tokenAddressOut);\n ++count;\n }\n }\n\n // Resize the array to the actual number of matching converters\n assembly {\n mstore(converters, count)\n mstore(convertersBalance, count)\n }\n sort(convertersBalance, converters);\n }\n\n /// @notice Used to get the index of the converter stored in the array\n /// This will return the index if the converter exists in the array otherwise will return type(uint128).max\n /// @param _tokenConverter Address of the token converter\n /// @return index of the converter address in the allConverters array\n function _findConverterIndex(IAbstractTokenConverter _tokenConverter) internal view returns (uint128 index) {\n index = type(uint128).max; // Not found, return a large value\n\n uint128 convertersLength = uint128(allConverters.length);\n for (uint128 i; i < convertersLength; ) {\n if (allConverters[i] == _tokenConverter) {\n index = i;\n }\n unchecked {\n ++i;\n }\n }\n }\n}\n" + }, + "contracts/TokenConverter/IAbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @notice Interface for AbstractTokenConverter\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ninterface IAbstractTokenConverter {\n /// @notice This enum define the all possible ways of conversion can happen\n enum ConversionAccessibility {\n NONE, // Conversion is disable for the pair\n ALL, // Conversion is enable for private conversion and users\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\n ONLY_FOR_USERS // Conversion is enable only for users\n }\n\n /// @notice This struct represents the configuration for a token conversion.\n struct ConversionConfig {\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\n uint256 incentive;\n /// enable or disable conversion for users or converters or both or none\n ConversionAccessibility conversionAccess;\n }\n\n /// @notice Pause conversion of tokens\n function pauseConversion() external;\n\n /// @notice Resume conversion of tokens.\n function resumeConversion() external;\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n function setPriceOracle(ResilientOracle priceOracle_) external;\n\n /// @notice Set the configuration for new or existing convert pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) external;\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Get the configuration for the pair of the tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\n /// @return conversionAccess Accessibility for the pair of tokens\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\n external\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\n\n /// @notice Get the address of the converterNetwork\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) external view returns (uint256 tokenBalance);\n}\n" + }, + "contracts/TokenConverter/RiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\nimport { IPoolRegistry } from \"../Interfaces/IPoolRegistry.sol\";\nimport { IComptroller } from \"../Interfaces/IComptroller.sol\";\nimport { IRiskFund, IRiskFundGetters } from \"../Interfaces/IRiskFund.sol\";\nimport { IVToken } from \"../Interfaces/IVToken.sol\";\n\n/// @title RiskFundConverter\n/// @author Venus\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the core pool comptroller\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n ///@notice Address of the vBNB\n ///@dev This address is used to include the BNB market while in getPools method\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable VBNB;\n\n ///@notice Address of the native wrapped currency\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_WRAPPED;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) internal assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\n\n /// @notice Address of pool registry contract\n address public poolRegistry;\n\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\n\n // Error thrown when comptrollers array length is not equal to assets array length\n error InvalidArguments();\n\n /// @notice thrown when amount entered is greater than balance\n error InsufficientBalance();\n\n /// @notice thrown when asset does not exist in the pool\n error MarketNotExistInPool(address comptroller, address asset);\n\n /// @notice thrown to prevent reentrancy\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\n /// cannot be called recursively within the same transaction.\n error ReentrancyGuardError();\n\n /// @param corePoolComptroller_ Address of the Comptroller pool\n /// @param vBNB_ Address of the vBNB\n /// @param nativeWrapped_ Address of the wrapped native currency\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) {\n ensureNonzeroAddress(corePoolComptroller_);\n ensureNonzeroAddress(vBNB_);\n ensureNonzeroAddress(nativeWrapped_);\n\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\n VBNB = vBNB_;\n NATIVE_WRAPPED = nativeWrapped_;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param poolRegistry_ Address of the pool registry\n /// @param minAmountToConvert_ minimum amount to convert\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address poolRegistry_,\n uint256 minAmountToConvert_,\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) public initializer {\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n ensureNonzeroAddress(poolRegistry_);\n poolRegistry = poolRegistry_;\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Pool registry setter\n /// @param poolRegistry_ Address of the pool registry\n /// @custom:event PoolRegistryUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:access Only Governance\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\n poolRegistry = poolRegistry_;\n }\n\n /// @notice Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:access Restricted by ACM\n function setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) external {\n _checkAccessAllowed(\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\");\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return reserves Asset's reserve in risk fund\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n reserves = poolsAssetsReserves[comptroller][asset];\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Reserves of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n tokenBalance = assetsReserves[tokenAddress];\n }\n\n /// @notice Get the array of all pools addresses\n /// @param tokenAddress Address of the token\n /// @return poolsWithCore Array of the pools addresses in which token is available\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\n\n if (isAssetListedInCore(tokenAddress)) {\n uint256 poolsLength = poolsWithCore.length;\n address[] memory extendedPools = new address[](poolsLength + 1);\n\n for (uint256 i; i < poolsLength; ) {\n extendedPools[i] = poolsWithCore[i];\n unchecked {\n ++i;\n }\n }\n\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\n poolsWithCore = extendedPools;\n }\n }\n\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\n assetsReserves[tokenOutAddress] -= amountOut;\n }\n\n /// @notice Hook to perform after converting tokens\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\n /// @param tokenInAddress Address of the tokenIn\n /// @param tokenOutAddress Address of the tokenOut\n /// @param amountIn Amount of tokenIn transferred\n /// @param amountOut Amount of tokenOut transferred\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\n function _postConversionHook(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) internal override {\n address[] memory pools = getPools(tokenOutAddress);\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\n ensureNonzeroValue(assetReserve);\n\n uint256 poolsLength = pools.length;\n uint256 distributedOutShare;\n uint256 poolAmountInShare;\n uint256 distributedInShare;\n\n for (uint256 i; i < poolsLength; ) {\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\n if (currentPoolsAssetsReserves != 0) {\n if (i < (poolsLength - 1)) {\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\n distributedInShare += poolAmountInShare;\n } else {\n uint256 distributedDiff = amountOut - distributedOutShare;\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\n poolAmountInShare = amountIn - distributedInShare;\n }\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\n }\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Operations to perform before sweeping tokens\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\n if (amount > balance) revert InsufficientBalance();\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\n\n if (balanceDiff < amount) {\n uint256 amountDiff;\n unchecked {\n amountDiff = amount - balanceDiff;\n }\n\n address[] memory pools = getPools(tokenAddress);\n uint256 assetReserve = assetsReserves[tokenAddress];\n uint256 poolsLength = pools.length;\n uint256 distributedShare;\n\n for (uint256 i; i < poolsLength; ) {\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\n if (i < (poolsLength - 1)) {\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\n } else {\n uint256 distributedDiff = amountDiff - distributedShare;\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\n }\n }\n unchecked {\n ++i;\n }\n }\n assetsReserves[tokenAddress] -= amountDiff;\n }\n }\n\n /// @dev Update the poolAssetsReserves upon transferring the tokens\n /// @param pool Address of the pool\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @param assetReserve Asset's reserve for the pool\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\n /// @custom:event AssetsReservesUpdated emits on success\n function updatePoolAssetsReserve(\n address pool,\n address tokenAddress,\n uint256 amount,\n uint256 assetReserve\n ) internal returns (uint256 poolAmountShare) {\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\n }\n\n /// @dev Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\n function _setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) internal {\n uint256 comptrollersLength = comptrollers.length;\n\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < comptrollersLength; ) {\n address[] memory poolAssets = assets[i];\n bool[] memory assetsValues = values[i];\n uint256 poolAssetsLength = poolAssets.length;\n\n if (poolAssetsLength != assetsValues.length) {\n revert InvalidArguments();\n }\n\n for (uint256 j; j < poolAssetsLength; ) {\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\n unchecked {\n ++j;\n }\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\n /// and transferring funds to the protocol share reserve\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return balanceDifference Amount of asset, for _privateConversion\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n function _updateAssetsState(address comptroller, address asset)\n internal\n override\n returns (uint256 balanceDifference)\n {\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 currentBalance = token.balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\n token.safeTransfer(destinationAddress, balanceDifference);\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\n\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\n IRiskFund(destinationAddress).updatePoolState(\n comptroller,\n asset,\n newDestinationBalance - previousDestinationBalance\n );\n balanceDifference = 0;\n }\n }\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n emit AssetTransferredToDestination(\n destinationAddress,\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance\n );\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @dev This function checks for the given asset is listed in core pool or not\n /// @param tokenAddress Address of the asset\n /// @return isAssetListed true if the asset is listed\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\n\n uint256 coreMarketsLength = coreMarkets.length;\n for (uint256 i; i < coreMarketsLength; ) {\n isAssetListed = (VBNB == coreMarkets[i])\n ? (tokenAddress == NATIVE_WRAPPED)\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\n\n if (isAssetListed) {\n break;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev This function checks for the given asset is listed or not\n /// @param comptroller Address of the comptroller\n /// @param asset Address of the asset\n /// @return isListed true if the asset is listed\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\n if (comptroller == CORE_POOL_COMPTROLLER) {\n isListed = isAssetListedInCore(asset);\n } else {\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\n }\n }\n\n /// @dev Get base asset address of the RiskFund\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/TokenConverter/SingleTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\n\n/// @title SingleTokenConverter\n/// @author Venus\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract SingleTokenConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the base asset token\n address public baseAsset;\n\n /// @notice Emitted when base asset is updated\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ Minimum amount to convert\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address baseAsset_,\n uint256 minAmountToConvert_\n ) public initializer {\n _setBaseAsset(baseAsset_);\n\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @notice Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:access Only Governance\n function setBaseAsset(address baseAsset_) external onlyOwner {\n _setBaseAsset(baseAsset_);\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address.\n /// @return balanceLeft Amount of asset, for _privateConversion\n // solhint-disable-next-line\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 balance = token.balanceOf(address(this));\n balanceLeft = balance;\n\n if (asset == baseAsset) {\n balanceLeft = 0;\n token.safeTransfer(destinationAddress, balance);\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\n }\n }\n\n /// @dev Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n /// @custom:event BaseAssetUpdated is emitted on success\n function _setBaseAsset(address baseAsset_) internal {\n ensureNonzeroAddress(baseAsset_);\n emit BaseAssetUpdated(baseAsset, baseAsset_);\n baseAsset = baseAsset_;\n }\n\n /// @dev Get base asset address\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = baseAsset;\n }\n}\n" + }, + "contracts/Utils/ArrayHelpers.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @notice Used to sort addresses array based on their token balances\n/// @param arr Array of token balances of different addresses\n/// @param addrs Array containing these addresses\nfunction sort(uint256[] memory arr, address[] memory addrs) pure {\n if (arr.length > 1) {\n return quickSortDescending(arr, addrs, 0, arr.length - 1);\n }\n}\n\n/// @notice Used to sort addresses array based on their token balances\n/// @param arr Array of token balances of different addresses\n/// @param addrs Array containing these addresses\n/// @param left index of first value\n/// @param right index of last value\nfunction quickSortDescending(\n uint256[] memory arr,\n address[] memory addrs,\n uint256 left,\n uint256 right\n) pure {\n if (left >= right) return;\n uint256 p = arr[(left + right) / 2]; // p = the pivot element\n uint256 i = left;\n uint256 j = right;\n while (i < j) {\n while (arr[i] > p) ++i;\n while (arr[j] < p) --j; // arr[j] < p means p still to the right, so j > 0\n if (arr[i] < arr[j]) {\n (arr[i], arr[j]) = (arr[j], arr[i]);\n (addrs[i], addrs[j]) = (addrs[j], addrs[i]);\n } else {\n ++i;\n }\n }\n\n if (j > left) quickSortDescending(arr, addrs, left, j - 1); // j > left, so j > 0\n quickSortDescending(arr, addrs, j + 1, right);\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} From 6d6ef46924918558534c5c09aded1184cbda6bae Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 25 Jan 2024 07:30:10 +0000 Subject: [PATCH 02/53] feat: updating deployment files --- deployments/bscmainnet.json | 50 ++++++++++++++++++++++++++- deployments/bscmainnet_addresses.json | 2 +- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/deployments/bscmainnet.json b/deployments/bscmainnet.json index 1214eb9f..184cf9d1 100644 --- a/deployments/bscmainnet.json +++ b/deployments/bscmainnet.json @@ -6901,7 +6901,7 @@ ] }, "RiskFundV2": { - "address": "0x5FA4E699eAFcf277d2Ed968bb9bc78F2fE9d04A3", + "address": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", "abi": [ { "inputs": [], @@ -7172,6 +7172,31 @@ "name": "SweepToken", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepTokenFromPool", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -7414,6 +7439,29 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepTokenFromPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/deployments/bscmainnet_addresses.json b/deployments/bscmainnet_addresses.json index 0a4ba085..adcf8f98 100644 --- a/deployments/bscmainnet_addresses.json +++ b/deployments/bscmainnet_addresses.json @@ -14,7 +14,7 @@ "RiskFundConverter": "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0", "RiskFundConverter_Implementation": "0x2fB02b3D49D45967DA471C7685Ce524d833520Dc", "RiskFundConverter_Proxy": "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0", - "RiskFundV2": "0x5FA4E699eAFcf277d2Ed968bb9bc78F2fE9d04A3", + "RiskFundV2": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", "SingleTokenConverterBeacon": "0x4c9D57b05B245c40235D720A5f3A592f3DfF11ca", "SingleTokenConverterImp": "0xe80f5A2adE24bEd740408B944197b3c24f2f2e91", "USDCPrimeConverter": "0xa758c9C215B6c4198F0a0e3FA46395Fa15Db691b", From 9591482b639fc6be0b61cfc19877cefb4da376e4 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Thu, 25 Jan 2024 13:21:27 +0530 Subject: [PATCH 03/53] feat: psr deployments on ethereum --- deployments/ethereum/.chainId | 1 + deployments/ethereum/DefaultProxyAdmin.json | 257 ++++ .../ethereum/ProtocolShareReserve.json | 1059 ++++++++++++++ .../ProtocolShareReserve_Implementation.json | 1280 +++++++++++++++++ .../ethereum/ProtocolShareReserve_Proxy.json | 277 ++++ .../0e89febeebc7444140de8e67c9067d2c.json | 78 + .../6da26d3137c108aa956c278f90b592e2.json | 228 +++ 7 files changed, 3180 insertions(+) create mode 100644 deployments/ethereum/.chainId create mode 100644 deployments/ethereum/DefaultProxyAdmin.json create mode 100644 deployments/ethereum/ProtocolShareReserve.json create mode 100644 deployments/ethereum/ProtocolShareReserve_Implementation.json create mode 100644 deployments/ethereum/ProtocolShareReserve_Proxy.json create mode 100644 deployments/ethereum/solcInputs/0e89febeebc7444140de8e67c9067d2c.json create mode 100644 deployments/ethereum/solcInputs/6da26d3137c108aa956c278f90b592e2.json diff --git a/deployments/ethereum/.chainId b/deployments/ethereum/.chainId new file mode 100644 index 00000000..56a6051c --- /dev/null +++ b/deployments/ethereum/.chainId @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/deployments/ethereum/DefaultProxyAdmin.json b/deployments/ethereum/DefaultProxyAdmin.json new file mode 100644 index 00000000..7d528b28 --- /dev/null +++ b/deployments/ethereum/DefaultProxyAdmin.json @@ -0,0 +1,257 @@ +{ + "address": "0x567e4cc5e085d09f66f836fa8279f38b4e5866b9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "transactionHash": "0x9e32d73e79893a1240580095cce39ef2adcaf9f70cd8d15661a12add85777b82", + "receipt": { + "to": null, + "from": "0x06a700eadc623db49f6dfab6535b316775526325", + "contractAddress": "0x567e4cc5e085d09f66f836fa8279f38b4e5866b9", + "transactionIndex": "0xfb", + "gasUsed": "0x9d443", + "logsBloom": "0x00000000000000000000000000000000000000000000000080800000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000020000000000000000000000000000000000000000000000000000000000040000000", + "blockHash": "0xf4a0efefe970f8e03c82ae72702863fc6c22c72bbd548cc18e8042de3d788bad", + "transactionHash": "0x9e32d73e79893a1240580095cce39ef2adcaf9f70cd8d15661a12add85777b82", + "logs": [ + { + "transactionHash": "0x9e32d73e79893a1240580095cce39ef2adcaf9f70cd8d15661a12add85777b82", + "address": "0x567e4cc5e085d09f66f836fa8279f38b4e5866b9", + "blockHash": "0xf4a0efefe970f8e03c82ae72702863fc6c22c72bbd548cc18e8042de3d788bad", + "blockNumber": "0x11d9009", + "data": "0x", + "logIndex": "0x1c5", + "removed": false, + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000285960c5b22fd66a736c7136967a3eb15e93cc67" + ], + "transactionIndex": "0xfb" + } + ], + "blockNumber": "0x11d9009", + "cumulativeGasUsed": "0x11b0dde", + "status": "0x1" + }, + "args": ["0x285960C5B22fD66A736C7136967A3eB15e93CC67"], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"initialOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeProxyAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"getProxyAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"getProxyImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"upgrade\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\",\"kind\":\"dev\",\"methods\":{\"changeProxyAdmin(address,address)\":{\"details\":\"Changes the admin of `proxy` to `newAdmin`. Requirements: - This contract must be the current admin of `proxy`.\"},\"getProxyAdmin(address)\":{\"details\":\"Returns the current admin of `proxy`. Requirements: - This contract must be the admin of `proxy`.\"},\"getProxyImplementation(address)\":{\"details\":\"Returns the current implementation of `proxy`. Requirements: - This contract must be the admin of `proxy`.\"},\"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.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgrade(address,address)\":{\"details\":\"Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. Requirements: - This contract must be the admin of `proxy`.\"},\"upgradeAndCall(address,address,bytes)\":{\"details\":\"Upgrades `proxy` to `implementation` and calls a function on the new implementation. See {TransparentUpgradeableProxy-upgradeToAndCall}. Requirements: - This contract must be the admin of `proxy`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol\":\"ProxyAdmin\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/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 (address initialOwner) {\\n _transferOwnership(initialOwner);\\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\":\"0x9b2bbba5bb04f53f277739c1cdff896ba8b3bf591cfc4eab2098c655e8ac251e\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./TransparentUpgradeableProxy.sol\\\";\\nimport \\\"../../access/Ownable.sol\\\";\\n\\n/**\\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\\n */\\ncontract ProxyAdmin is Ownable {\\n\\n constructor (address initialOwner) Ownable(initialOwner) {}\\n\\n /**\\n * @dev Returns the current implementation of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"implementation()\\\")) == 0x5c60da1b\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"5c60da1b\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Returns the current admin of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"admin()\\\")) == 0xf851a440\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"f851a440\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Changes the admin of `proxy` to `newAdmin`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the current admin of `proxy`.\\n */\\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\\n proxy.changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\\n proxy.upgradeTo(implementation);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgradeAndCall(\\n TransparentUpgradeableProxy proxy,\\n address implementation,\\n bytes memory data\\n ) public payable virtual onlyOwner {\\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\\n }\\n}\\n\",\"keccak256\":\"0x754888b9c9ab5525343460b0a4fa2e2f4fca9b6a7e0e7ddea4154e2b1182a45d\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/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\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50604051610b17380380610b1783398101604081905261002f91610090565b8061003981610040565b50506100c0565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100a257600080fd5b81516001600160a01b03811681146100b957600080fd5b9392505050565b610a48806100cf6000396000f3fe60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461012b57806399a88ec41461013e578063f2fde38b1461015e578063f3b7dead1461017e57600080fd5b8063204e1c7a14610080578063715018a6146100c95780637eff275e146100e05780638da5cb5b14610100575b600080fd5b34801561008c57600080fd5b506100a061009b3660046107e4565b61019e565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100de610255565b005b3480156100ec57600080fd5b506100de6100fb366004610808565b6102e7565b34801561010c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100a0565b6100de610139366004610870565b6103ee565b34801561014a57600080fd5b506100de610159366004610808565b6104fc565b34801561016a57600080fd5b506100de6101793660046107e4565b6105d1565b34801561018a57600080fd5b506100a06101993660046107e4565b610701565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610225576040519150601f19603f3d011682016040523d82523d6000602084013e61022a565b606091505b50915091508161023957600080fd5b8080602001905181019061024d9190610964565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6102e5600061074d565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b600060405180830381600087803b1580156103d257600080fd5b505af11580156103e6573d6000803e3d6000fd5b505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461046f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef2869034906104c59086908690600401610981565b6000604051808303818588803b1580156104de57600080fd5b505af11580156104f2573d6000803e3d6000fd5b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461057d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016103b8565b60005473ffffffffffffffffffffffffffffffffffffffff163314610652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b73ffffffffffffffffffffffffffffffffffffffff81166106f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102d2565b6106fe8161074d565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146106fe57600080fd5b6000602082840312156107f657600080fd5b8135610801816107c2565b9392505050565b6000806040838503121561081b57600080fd5b8235610826816107c2565b91506020830135610836816107c2565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561088557600080fd5b8335610890816107c2565b925060208401356108a0816107c2565b9150604084013567ffffffffffffffff808211156108bd57600080fd5b818601915086601f8301126108d157600080fd5b8135818111156108e3576108e3610841565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561092957610929610841565b8160405282815289602084870101111561094257600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561097657600080fd5b8151610801816107c2565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b818110156109cb578581018301518582016060015282016109af565b818111156109dd576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160600194935050505056fea2646970667358221220bd6c09ab03bfaf9ec60a4bf8cd98903cecb891974e17e2d76a3b2002c97eeb8964736f6c634300080a0033", + "deployedBytecode": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461012b57806399a88ec41461013e578063f2fde38b1461015e578063f3b7dead1461017e57600080fd5b8063204e1c7a14610080578063715018a6146100c95780637eff275e146100e05780638da5cb5b14610100575b600080fd5b34801561008c57600080fd5b506100a061009b3660046107e4565b61019e565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100de610255565b005b3480156100ec57600080fd5b506100de6100fb366004610808565b6102e7565b34801561010c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100a0565b6100de610139366004610870565b6103ee565b34801561014a57600080fd5b506100de610159366004610808565b6104fc565b34801561016a57600080fd5b506100de6101793660046107e4565b6105d1565b34801561018a57600080fd5b506100a06101993660046107e4565b610701565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610225576040519150601f19603f3d011682016040523d82523d6000602084013e61022a565b606091505b50915091508161023957600080fd5b8080602001905181019061024d9190610964565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6102e5600061074d565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b600060405180830381600087803b1580156103d257600080fd5b505af11580156103e6573d6000803e3d6000fd5b505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461046f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef2869034906104c59086908690600401610981565b6000604051808303818588803b1580156104de57600080fd5b505af11580156104f2573d6000803e3d6000fd5b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461057d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016103b8565b60005473ffffffffffffffffffffffffffffffffffffffff163314610652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b73ffffffffffffffffffffffffffffffffffffffff81166106f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102d2565b6106fe8161074d565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146106fe57600080fd5b6000602082840312156107f657600080fd5b8135610801816107c2565b9392505050565b6000806040838503121561081b57600080fd5b8235610826816107c2565b91506020830135610836816107c2565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561088557600080fd5b8335610890816107c2565b925060208401356108a0816107c2565b9150604084013567ffffffffffffffff808211156108bd57600080fd5b818601915086601f8301126108d157600080fd5b8135818111156108e3576108e3610841565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561092957610929610841565b8160405282815289602084870101111561094257600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561097657600080fd5b8151610801816107c2565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b818110156109cb578581018301518582016060015282016109af565b818111156109dd576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160600194935050505056fea2646970667358221220bd6c09ab03bfaf9ec60a4bf8cd98903cecb891974e17e2d76a3b2002c97eeb8964736f6c634300080a0033", + "devdoc": { + "details": "This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.", + "kind": "dev", + "methods": { + "changeProxyAdmin(address,address)": { + "details": "Changes the admin of `proxy` to `newAdmin`. Requirements: - This contract must be the current admin of `proxy`." + }, + "getProxyAdmin(address)": { + "details": "Returns the current admin of `proxy`. Requirements: - This contract must be the admin of `proxy`." + }, + "getProxyImplementation(address)": { + "details": "Returns the current implementation of `proxy`. Requirements: - This contract must be the admin of `proxy`." + }, + "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." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgrade(address,address)": { + "details": "Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. Requirements: - This contract must be the admin of `proxy`." + }, + "upgradeAndCall(address,address,bytes)": { + "details": "Upgrades `proxy` to `implementation` and calls a function on the new implementation. See {TransparentUpgradeableProxy-upgradeToAndCall}. Requirements: - This contract must be the admin of `proxy`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} diff --git a/deployments/ethereum/ProtocolShareReserve.json b/deployments/ethereum/ProtocolShareReserve.json new file mode 100644 index 00000000..e84d457c --- /dev/null +++ b/deployments/ethereum/ProtocolShareReserve.json @@ -0,0 +1,1059 @@ +{ + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "percent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "oldPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPoolRegistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" + } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" + } + ], + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolRegistry", + "type": "address" + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ], + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "receipt": { + "to": null, + "from": "0x0Fd46ceD479C35d3116553Ae2DF190648CFD19Dd", + "contractAddress": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "transactionIndex": 69, + "gasUsed": "842949", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000000000000000000002000000000000000000000008000000000000000000000000000000002000001000000000002000000000800000000000000020000000000000000000800000080800001000000000000000000400000000000000000000000000000000080000000000080000000000000800000000000000000000000002000000400000000000100800000000000000000000000000020000000000000000001040000000000000400000800000000000020000000000200000000000000000000000000000800000000000000000000000000", + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc", + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "logs": [ + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000ee934792431b4ebd91591a86c884a8b49ed494c2" + ], + "data": "0x", + "logIndex": 85, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + }, + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000fd46ced479c35d3116553ae2df190648cfd19dd" + ], + "data": "0x", + "logIndex": 86, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + }, + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 87, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + }, + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014", + "logIndex": 88, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + }, + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 89, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + }, + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000567e4cc5e085d09f66f836fa8279f38b4e5866b9", + "logIndex": 90, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + } + ], + "blockNumber": 19081788, + "cumulativeGasUsed": "4625878", + "status": 1, + "byzantium": true + }, + "args": [ + "0xee934792431B4Ebd91591a86c884A8b49Ed494C2", + "0x567e4cc5e085d09f66f836fa8279f38b4e5866b9", + "0xcd6dc68700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000014" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "execute": { + "methodName": "initialize", + "args": ["0x0000000000000000000000000000000000000001", 20] + }, + "implementation": "0xee934792431B4Ebd91591a86c884A8b49Ed494C2", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/ethereum/ProtocolShareReserve_Implementation.json b/deployments/ethereum/ProtocolShareReserve_Implementation.json new file mode 100644 index 00000000..5b159c4b --- /dev/null +++ b/deployments/ethereum/ProtocolShareReserve_Implementation.json @@ -0,0 +1,1280 @@ +{ + "address": "0xee934792431B4Ebd91591a86c884A8b49Ed494C2", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_corePoolComptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "_wbnb", + "type": "address" + }, + { + "internalType": "address", + "name": "_vbnb", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "percent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "oldPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPoolRegistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" + } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" + } + ], + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolRegistry", + "type": "address" + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x357fbe8987d1f442b8112fe3ea09e11bf66ee84c1ba1fd4855c33ec79776c73a", + "receipt": { + "to": null, + "from": "0x0Fd46ceD479C35d3116553Ae2DF190648CFD19Dd", + "contractAddress": "0xee934792431B4Ebd91591a86c884A8b49Ed494C2", + "transactionIndex": 177, + "gasUsed": "2587309", + "logsBloom": "0x00000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000", + "blockHash": "0x4ef34c79eefcb39a562eb0f9a8fcb0a4100499e8ee0febb93444976361ecceab", + "transactionHash": "0x357fbe8987d1f442b8112fe3ea09e11bf66ee84c1ba1fd4855c33ec79776c73a", + "logs": [ + { + "transactionIndex": 177, + "blockNumber": 19081787, + "transactionHash": "0x357fbe8987d1f442b8112fe3ea09e11bf66ee84c1ba1fd4855c33ec79776c73a", + "address": "0xee934792431B4Ebd91591a86c884A8b49Ed494C2", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", + "logIndex": 239, + "blockHash": "0x4ef34c79eefcb39a562eb0f9a8fcb0a4100499e8ee0febb93444976361ecceab" + } + ], + "blockNumber": 19081787, + "cumulativeGasUsed": "13135204", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000001" + ], + "numDeployments": 1, + "solcInputHash": "6da26d3137c108aa956c278f90b592e2", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_corePoolComptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_wbnb\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_vbnb\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTotalPercentage\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IProtocolShareReserve.IncomeType\",\"name\":\"incomeType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"}],\"name\":\"AssetsReservesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"percentage\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"}],\"name\":\"DistributionConfigAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"percentage\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"}],\"name\":\"DistributionConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"oldPercentage\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"newPercentage\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"}],\"name\":\"DistributionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPoolRegistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPoolRegistry\",\"type\":\"address\"}],\"name\":\"PoolRegistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"ReservesUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_COMPTROLLER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PERCENT\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WBNB\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"internalType\":\"uint16\",\"name\":\"percentage\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"internalType\":\"struct ProtocolShareReserve.DistributionConfig[]\",\"name\":\"configs\",\"type\":\"tuple[]\"}],\"name\":\"addOrUpdateDistributionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"distributionTargets\",\"outputs\":[{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"internalType\":\"uint16\",\"name\":\"percentage\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"}],\"name\":\"getPercentageDistribution\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getUnreleasedFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_accessControlManager\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_loopsLimit\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLoopsLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"assets\",\"type\":\"address[]\"}],\"name\":\"releaseFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"removeDistributionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_poolRegistry\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"totalAssetReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalDistributions\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"enum IProtocolShareReserve.IncomeType\",\"name\":\"incomeType\",\"type\":\"uint8\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vBNB\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"addOrUpdateDistributionConfigs((uint8,uint16,address)[])\":{\"details\":\"Add or update destination targets based on destination address\",\"params\":{\"configs\":\"configurations of the destinations.\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"getPercentageDistribution(address,uint8)\":{\"details\":\"Used to find out the percentage distribution for a particular destination based on schema\",\"params\":{\"destination\":\"the destination address of the distribution target\",\"schema\":\"the schema of the distribution target\"},\"returns\":{\"_0\":\"percentage percentage distribution\"}},\"getUnreleasedFunds(address,uint8,address,address)\":{\"details\":\"Used to find out the amount of funds that's going to be released when release funds is called.\",\"params\":{\"asset\":\"the asset address which will be released\",\"comptroller\":\"the comptroller address of the pool\",\"destination\":\"the destination address of the distribution target\",\"schema\":\"the schema of the distribution target\"}},\"initialize(address,uint256)\":{\"details\":\"Initializes the deployer to owner.\",\"params\":{\"_accessControlManager\":\"The address of ACM contract\",\"_loopsLimit\":\"Limit for the loops in the contract to avoid DOS\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"releaseFunds(address,address[])\":{\"details\":\"Release funds\",\"params\":{\"assets\":\"assets to be released to distribution targets\",\"comptroller\":\"the comptroller address of the pool\"}},\"removeDistributionConfig(uint8,address)\":{\"details\":\"Remove destionation target if percentage is 0\",\"params\":{\"destination\":\"destination address of the configuration\",\"schema\":\"schema of the configuration\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"details\":\"Pool registry setter.\",\"params\":{\"_poolRegistry\":\"Address of the pool registry\"}},\"totalDistributions()\":{\"details\":\"Returns the total number of distribution targets\"},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address,uint8)\":{\"details\":\"Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\",\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address (pool)\",\"incomeType\":\"type of income\"}}},\"stateVariables\":{\"CORE_POOL_COMPTROLLER\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"WBNB\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"vBNB\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"}},\"version\":1},\"userdoc\":{\"errors\":{\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetReleased(address,address,uint8,uint256,uint256)\":{\"notice\":\"Event emitted when an asset is released to a target\"},\"AssetsReservesUpdated(address,address,uint256,uint8,uint8)\":{\"notice\":\"Event emitted after updating of the assets reserves.\"},\"DistributionConfigAdded(address,uint16,uint8)\":{\"notice\":\"Event emitted when distribution configuration is added\"},\"DistributionConfigRemoved(address,uint16,uint8)\":{\"notice\":\"Event emitted when distribution configuration is removed\"},\"DistributionConfigUpdated(address,uint16,uint16,uint8)\":{\"notice\":\"Event emitted when distribution configuration is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ReservesUpdated(address,address,uint8,uint256,uint256)\":{\"notice\":\"Event emitted when asset reserves state is updated\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_COMPTROLLER()\":{\"notice\":\"address of core pool comptroller contract\"},\"WBNB()\":{\"notice\":\"address of WBNB contract\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"assetsReserves(address,address,uint8)\":{\"notice\":\"comptroller => asset => schema => balance\"},\"distributionTargets(uint256)\":{\"notice\":\"configuration for different income distribution targets\"},\"poolRegistry()\":{\"notice\":\"address of pool registry contract\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"totalAssetReserve(address)\":{\"notice\":\"asset => balance\"},\"vBNB()\":{\"notice\":\"address of vBNB contract\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ProtocolReserve/ProtocolShareReserve.sol\":\"ProtocolShareReserve\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title MaxLoopsLimitHelper\\n * @author Venus\\n * @notice Abstract contract used to avoid collection with too many items that would generate gas errors and DoS.\\n */\\nabstract contract MaxLoopsLimitHelper {\\n // Limit for the loops to avoid the DOS\\n uint256 public maxLoopsLimit;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when max loops limit is set\\n event MaxLoopsLimitUpdated(uint256 oldMaxLoopsLimit, uint256 newmaxLoopsLimit);\\n\\n /// @notice Thrown an error on maxLoopsLimit exceeds for any loop\\n error MaxLoopsLimitExceeded(uint256 loopsLimit, uint256 requiredLoops);\\n\\n /**\\n * @notice Set the limit for the loops can iterate to avoid the DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function _setMaxLoopsLimit(uint256 limit) internal {\\n require(limit > maxLoopsLimit, \\\"Comptroller: Invalid maxLoopsLimit\\\");\\n\\n uint256 oldMaxLoopsLimit = maxLoopsLimit;\\n maxLoopsLimit = limit;\\n\\n emit MaxLoopsLimitUpdated(oldMaxLoopsLimit, limit);\\n }\\n\\n /**\\n * @notice Compare the maxLoopsLimit with number of the times loop iterate\\n * @param len Length of the loops iterate\\n * @custom:error MaxLoopsLimitExceeded error is thrown when loops length exceeds maxLoopsLimit\\n */\\n function _ensureMaxLoops(uint256 len) internal view {\\n if (len > maxLoopsLimit) {\\n revert MaxLoopsLimitExceeded(maxLoopsLimit, len);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98c97af128677629375ca93e8d8ca3f337a4abf9304a0a4ddaea9d96cc554c3b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IComptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IComptroller {\\n function isComptroller() external view returns (bool);\\n\\n function markets(address) external view returns (bool);\\n\\n function getAllMarkets() external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x7d85db8d34103352b25f29f591c1e45159222f0d2bbafaa3fcd42f42bf9a523d\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IIncomeDestination.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IIncomeDestination {\\n function updateAssetsState(address comptroller, address asset) external;\\n}\\n\",\"keccak256\":\"0xd04c051f6aaa914193353843e2d7080a7dcb88dfca2a7ce1612b0b0849cbe49d\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IPoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IPoolRegistry {\\n /// @notice Get VToken in the Pool for an Asset\\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\\n\\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb38a3b61926e55588096e0657b758b178130386143a5658030d659038ec7075c\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0xe1267c8d6c024414f636bfac1c0cb166504f7ba420341bb5d474a27f1c77e136\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IVToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IVToken {\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x0718e50835da441b2dddcf6d52a671c43d386b96dbcc9eb41d68c3647b82c117\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/ProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { IProtocolShareReserve } from \\\"../Interfaces/IProtocolShareReserve.sol\\\";\\nimport { IComptroller } from \\\"../Interfaces/IComptroller.sol\\\";\\nimport { IPoolRegistry } from \\\"../Interfaces/IPoolRegistry.sol\\\";\\nimport { IVToken } from \\\"../Interfaces/IVToken.sol\\\";\\nimport { IIncomeDestination } from \\\"../Interfaces/IIncomeDestination.sol\\\";\\n\\nerror InvalidAddress();\\nerror UnsupportedAsset();\\nerror InvalidTotalPercentage();\\nerror InvalidMaxLoopsLimit();\\n\\ncontract ProtocolShareReserve is\\n AccessControlledV8,\\n ReentrancyGuardUpgradeable,\\n MaxLoopsLimitHelper,\\n IProtocolShareReserve\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice protocol income is categorized into two schemas.\\n /// The first schema is for spread income\\n /// The second schema is for liquidation income\\n enum Schema {\\n PROTOCOL_RESERVES,\\n ADDITIONAL_REVENUE\\n }\\n\\n struct DistributionConfig {\\n Schema schema;\\n /// @dev percenatge is represented without any scale\\n uint16 percentage;\\n address destination;\\n }\\n\\n /// @notice address of core pool comptroller contract\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable CORE_POOL_COMPTROLLER;\\n\\n /// @notice address of WBNB contract\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable WBNB;\\n\\n /// @notice address of vBNB contract\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vBNB;\\n\\n /// @notice address of pool registry contract\\n address public poolRegistry;\\n\\n uint16 public constant MAX_PERCENT = 1e4;\\n\\n /// @notice comptroller => asset => schema => balance\\n mapping(address => mapping(address => mapping(Schema => uint256))) public assetsReserves;\\n\\n /// @notice asset => balance\\n mapping(address => uint256) public totalAssetReserve;\\n\\n /// @notice configuration for different income distribution targets\\n DistributionConfig[] public distributionTargets;\\n\\n /// @notice Emitted when pool registry address is updated\\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\\n\\n /// @notice Event emitted after updating of the assets reserves.\\n event AssetsReservesUpdated(\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount,\\n IncomeType incomeType,\\n Schema schema\\n );\\n\\n /// @notice Event emitted when an asset is released to a target\\n event AssetReleased(\\n address indexed destination,\\n address indexed asset,\\n Schema schema,\\n uint256 percent,\\n uint256 amount\\n );\\n\\n /// @notice Event emitted when asset reserves state is updated\\n event ReservesUpdated(\\n address indexed comptroller,\\n address indexed asset,\\n Schema schema,\\n uint256 oldBalance,\\n uint256 newBalance\\n );\\n\\n /// @notice Event emitted when distribution configuration is updated\\n event DistributionConfigUpdated(\\n address indexed destination,\\n uint16 oldPercentage,\\n uint16 newPercentage,\\n Schema schema\\n );\\n\\n /// @notice Event emitted when distribution configuration is added\\n event DistributionConfigAdded(address indexed destination, uint16 percentage, Schema schema);\\n\\n /// @notice Event emitted when distribution configuration is removed\\n event DistributionConfigRemoved(address indexed destination, uint16 percentage, Schema schema);\\n\\n /**\\n * @dev Constructor to initialize the immutable variables\\n * @param _corePoolComptroller The address of core pool comptroller\\n * @param _wbnb The address of WBNB\\n * @param _vbnb The address of vBNB\\n */\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address _corePoolComptroller,\\n address _wbnb,\\n address _vbnb\\n ) {\\n ensureNonzeroAddress(_corePoolComptroller);\\n ensureNonzeroAddress(_wbnb);\\n ensureNonzeroAddress(_vbnb);\\n\\n CORE_POOL_COMPTROLLER = _corePoolComptroller;\\n WBNB = _wbnb;\\n vBNB = _vbnb;\\n\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @dev Initializes the deployer to owner.\\n * @param _accessControlManager The address of ACM contract\\n * @param _loopsLimit Limit for the loops in the contract to avoid DOS\\n */\\n function initialize(address _accessControlManager, uint256 _loopsLimit) external initializer {\\n __AccessControlled_init(_accessControlManager);\\n __ReentrancyGuard_init();\\n _setMaxLoopsLimit(_loopsLimit);\\n }\\n\\n /**\\n * @dev Pool registry setter.\\n * @param _poolRegistry Address of the pool registry\\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n */\\n function setPoolRegistry(address _poolRegistry) external onlyOwner {\\n ensureNonzeroAddress(_poolRegistry);\\n emit PoolRegistryUpdated(poolRegistry, _poolRegistry);\\n poolRegistry = _poolRegistry;\\n }\\n\\n /**\\n * @dev Add or update destination targets based on destination address\\n * @param configs configurations of the destinations.\\n */\\n function addOrUpdateDistributionConfigs(DistributionConfig[] calldata configs) external nonReentrant {\\n _checkAccessAllowed(\\\"addOrUpdateDistributionConfigs(DistributionConfig[])\\\");\\n\\n for (uint256 i = 0; i < configs.length; ) {\\n DistributionConfig memory _config = configs[i];\\n ensureNonzeroAddress(_config.destination);\\n\\n bool updated = false;\\n uint256 distributionTargetsLength = distributionTargets.length;\\n for (uint256 j = 0; j < distributionTargetsLength; ) {\\n DistributionConfig storage config = distributionTargets[j];\\n\\n if (_config.schema == config.schema && config.destination == _config.destination) {\\n emit DistributionConfigUpdated(\\n _config.destination,\\n config.percentage,\\n _config.percentage,\\n _config.schema\\n );\\n config.percentage = _config.percentage;\\n updated = true;\\n break;\\n }\\n\\n unchecked {\\n ++j;\\n }\\n }\\n\\n if (!updated) {\\n distributionTargets.push(_config);\\n emit DistributionConfigAdded(_config.destination, _config.percentage, _config.schema);\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n _ensurePercentages();\\n _ensureMaxLoops(distributionTargets.length);\\n }\\n\\n /**\\n * @dev Remove destionation target if percentage is 0\\n * @param schema schema of the configuration\\n * @param destination destination address of the configuration\\n */\\n function removeDistributionConfig(Schema schema, address destination) external {\\n _checkAccessAllowed(\\\"removeDistributionConfig(Schema,address)\\\");\\n\\n uint256 distributionIndex;\\n bool found = false;\\n for (uint256 i = 0; i < distributionTargets.length; ) {\\n DistributionConfig storage config = distributionTargets[i];\\n\\n if (schema == config.schema && destination == config.destination && config.percentage == 0) {\\n found = true;\\n distributionIndex = i;\\n break;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n if (found) {\\n emit DistributionConfigRemoved(\\n distributionTargets[distributionIndex].destination,\\n distributionTargets[distributionIndex].percentage,\\n distributionTargets[distributionIndex].schema\\n );\\n\\n distributionTargets[distributionIndex] = distributionTargets[distributionTargets.length - 1];\\n distributionTargets.pop();\\n }\\n\\n _ensurePercentages();\\n }\\n\\n /**\\n * @dev Release funds\\n * @param comptroller the comptroller address of the pool\\n * @param assets assets to be released to distribution targets\\n */\\n function releaseFunds(address comptroller, address[] calldata assets) external nonReentrant {\\n for (uint256 i = 0; i < assets.length; ) {\\n _releaseFund(comptroller, assets[i]);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @dev Used to find out the amount of funds that's going to be released when release funds is called.\\n * @param comptroller the comptroller address of the pool\\n * @param schema the schema of the distribution target\\n * @param destination the destination address of the distribution target\\n * @param asset the asset address which will be released\\n */\\n function getUnreleasedFunds(\\n address comptroller,\\n Schema schema,\\n address destination,\\n address asset\\n ) external view returns (uint256) {\\n uint256 distributionTargetsLength = distributionTargets.length;\\n for (uint256 i = 0; i < distributionTargetsLength; ) {\\n DistributionConfig storage _config = distributionTargets[i];\\n if (_config.schema == schema && _config.destination == destination) {\\n uint256 total = assetsReserves[comptroller][asset][schema];\\n return (total * _config.percentage) / MAX_PERCENT;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the total number of distribution targets\\n */\\n function totalDistributions() external view returns (uint256) {\\n return distributionTargets.length;\\n }\\n\\n /**\\n * @dev Used to find out the percentage distribution for a particular destination based on schema\\n * @param destination the destination address of the distribution target\\n * @param schema the schema of the distribution target\\n * @return percentage percentage distribution\\n */\\n function getPercentageDistribution(address destination, Schema schema) external view returns (uint256) {\\n uint256 distributionTargetsLength = distributionTargets.length;\\n for (uint256 i = 0; i < distributionTargetsLength; ) {\\n DistributionConfig memory config = distributionTargets[i];\\n\\n if (config.destination == destination && config.schema == schema) {\\n return config.percentage;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @dev Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\\n * @param comptroller Comptroller address (pool)\\n * @param asset Asset address.\\n * @param incomeType type of income\\n */\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) public override(IProtocolShareReserve) nonReentrant {\\n if (!IComptroller(comptroller).isComptroller()) revert InvalidAddress();\\n ensureNonzeroAddress(asset);\\n\\n if (\\n comptroller != CORE_POOL_COMPTROLLER &&\\n IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) == address(0)\\n ) revert InvalidAddress();\\n\\n Schema schema = _getSchema(incomeType);\\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\\n uint256 assetReserve = totalAssetReserve[asset];\\n\\n if (currentBalance > assetReserve) {\\n uint256 balanceDifference;\\n unchecked {\\n balanceDifference = currentBalance - assetReserve;\\n }\\n\\n assetsReserves[comptroller][asset][schema] += balanceDifference;\\n totalAssetReserve[asset] += balanceDifference;\\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference, incomeType, schema);\\n }\\n }\\n\\n /**\\n * @dev asset from a particular pool to be release to distribution targets\\n * @param comptroller Comptroller address(pool)\\n * @param asset Asset address.\\n */\\n function _releaseFund(address comptroller, address asset) internal {\\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\\n uint256[] memory schemaBalances = new uint256[](totalSchemas);\\n uint256 totalBalance;\\n for (uint256 schemaValue; schemaValue < totalSchemas; ) {\\n schemaBalances[schemaValue] = assetsReserves[comptroller][asset][Schema(schemaValue)];\\n totalBalance += schemaBalances[schemaValue];\\n\\n unchecked {\\n ++schemaValue;\\n }\\n }\\n\\n if (totalBalance == 0) {\\n return;\\n }\\n\\n uint256[] memory totalTransferAmounts = new uint256[](totalSchemas);\\n for (uint256 i = 0; i < distributionTargets.length; ) {\\n DistributionConfig memory _config = distributionTargets[i];\\n\\n uint256 transferAmount = (schemaBalances[uint256(_config.schema)] * _config.percentage) / MAX_PERCENT;\\n totalTransferAmounts[uint256(_config.schema)] += transferAmount;\\n\\n if (transferAmount != 0) {\\n IERC20Upgradeable(asset).safeTransfer(_config.destination, transferAmount);\\n IIncomeDestination(_config.destination).updateAssetsState(comptroller, asset);\\n\\n emit AssetReleased(_config.destination, asset, _config.schema, _config.percentage, transferAmount);\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256[] memory newSchemaBalances = new uint256[](totalSchemas);\\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\\n newSchemaBalances[schemaValue] = schemaBalances[schemaValue] - totalTransferAmounts[schemaValue];\\n assetsReserves[comptroller][asset][Schema(schemaValue)] = newSchemaBalances[schemaValue];\\n totalAssetReserve[asset] = totalAssetReserve[asset] - totalTransferAmounts[schemaValue];\\n\\n emit ReservesUpdated(\\n comptroller,\\n asset,\\n Schema(schemaValue),\\n schemaBalances[schemaValue],\\n newSchemaBalances[schemaValue]\\n );\\n\\n unchecked {\\n ++schemaValue;\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the schema based on income type\\n * @param incomeType type of income\\n * @return schema schema for distribution\\n */\\n function _getSchema(IncomeType incomeType) internal view returns (Schema schema) {\\n schema = Schema.ADDITIONAL_REVENUE;\\n\\n if (incomeType == IncomeType.SPREAD) {\\n schema = Schema.PROTOCOL_RESERVES;\\n }\\n }\\n\\n /**\\n * @dev This ensures that the total percentage of all the distribution targets is 100% or 0%\\n */\\n function _ensurePercentages() internal view {\\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\\n uint16[] memory totalPercentages = new uint16[](totalSchemas);\\n\\n uint256 distributionTargetsLength = distributionTargets.length;\\n for (uint256 i = 0; i < distributionTargetsLength; ) {\\n DistributionConfig memory config = distributionTargets[i];\\n totalPercentages[uint256(config.schema)] += config.percentage;\\n\\n unchecked {\\n ++i;\\n }\\n }\\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\\n if (totalPercentages[schemaValue] != MAX_PERCENT && totalPercentages[schemaValue] != 0)\\n revert InvalidTotalPercentage();\\n\\n unchecked {\\n ++schemaValue;\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the underlying asset address for the vToken\\n * @param vToken vToken address\\n * @return asset address of asset\\n */\\n function _getUnderlying(address vToken) internal view returns (address) {\\n if (vToken == vBNB) {\\n return WBNB;\\n } else {\\n return IVToken(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x18a958e20fae4e3aa04f109a69e45d3e86681f6b052bc35715f2dc3f69b35670\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162002f8738038062002f8783398101604081905262000034916200018a565b6200003f8362000081565b6200004a8262000081565b620000558162000081565b6001600160a01b0380841660805282811660a052811660c05262000078620000ac565b505050620001d4565b6001600160a01b038116620000a9576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff1615620001195760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016b576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018557600080fd5b919050565b600080600060608486031215620001a057600080fd5b620001ab846200016d565b9250620001bb602085016200016d565b9150620001cb604085016200016d565b90509250925092565b60805160a05160c051612d7c6200020b6000396000610209015260006103090152600081816103c901526104bc0152612d7c6000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c8063893ffe98116100ee578063b4a0bdf311610097578063e30c397811610071578063e30c3978146103a0578063f2fde38b146103b1578063fa7b81a0146103c4578063fc31116a146103eb57600080fd5b8063b4a0bdf314610373578063be26317e14610384578063cd6dc6871461038d57600080fd5b8063966961f0116100c8578063966961f01461032b578063aea211211461033e578063afcff50f1461035f57600080fd5b8063893ffe98146102e05780638da5cb5b146102f35780638dd950021461030457600080fd5b80634f429f3611610150578063715018a61161012a578063715018a6146102bd57806379ba5097146102c55780637b77cd6a146102cd57600080fd5b80634f429f36146102655780635db6da12146102785780635f3d6133146102aa57600080fd5b806316faecec1161018157806316faecec146101f157806333e1567f14610204578063392ee7121461024357600080fd5b80630e32cb86146101a85780631036bbe2146101bd578063163db71b146101de575b600080fd5b6101bb6101b63660046125a8565b6103fe565b005b6101c661271081565b60405161ffff90911681526020015b60405180910390f35b610130545b6040519081526020016101d5565b6101bb6101ff3660046125d9565b610412565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101d5565b610256610251366004612624565b610788565b6040516101d5939291906126a3565b6101bb6102733660046126d1565b6107c8565b6101e36102863660046125d9565b61012e60209081526000938452604080852082529284528284209052825290205481565b6101bb6102b836600461270a565b610b0a565b6101bb610e19565b6101bb610e2d565b6101bb6102db3660046125a8565b610ebd565b6101e36102ee36600461277f565b610f44565b6033546001600160a01b031661022b565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6101e36103393660046127db565b611066565b6101e361034c3660046125a8565b61012f6020526000908152604090205481565b61012d5461022b906001600160a01b031681565b6097546001600160a01b031661022b565b6101e360fb5481565b6101bb61039b366004612809565b61115b565b6065546001600160a01b031661022b565b6101bb6103bf3660046125a8565b6112e6565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6101bb6103f9366004612835565b61136f565b6104066113c5565b61040f8161141f565b50565b61041a611515565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610457573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047b91906128bd565b6104b1576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104ba8261156e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614158015610593575061012d546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015610564573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058891906128df565b6001600160a01b0316145b156105ca576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105d5826115ae565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038516906370a0823190602401602060405180830381865afa158015610638573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065c91906128fc565b6001600160a01b038516600090815261012f602052604090205490915080821115610776576001600160a01b03808716600090815261012e602090815260408083209389168352929052908120828403918291908660018111156106c2576106c261263d565b60018111156106d3576106d361263d565b815260200190815260200160002060008282546106f09190612944565b90915550506001600160a01b038616600090815261012f60205260408120805483929061071e908490612944565b92505081905550856001600160a01b0316876001600160a01b03167fa46b2431e663cf7b50c9d5129aff85d2394ecfd447b7ccba83986510a9d945ea83888860405161076c9392919061295c565b60405180910390a3505b505050610783600160c955565b505050565b610130818154811061079957600080fd5b60009182526020909120015460ff81169150610100810461ffff1690630100000090046001600160a01b031683565b6107e9604051806060016040528060288152602001612ceb602891396115d9565b600080805b61013054811015610894576000610130828154811061080f5761080f612989565b6000918252602090912001805490915060ff1660018111156108335761083361263d565b8660018111156108455761084561263d565b148015610865575080546001600160a01b03868116630100000090920416145b801561087957508054610100900461ffff16155b1561088b576001925081935050610894565b506001016107ee565b508015610afc5761013082815481106108af576108af612989565b9060005260206000200160000160039054906101000a90046001600160a01b03166001600160a01b03167f70e7a210881df49522a5bf05d477e00d59e52a41c96c1eedeaeb356b9e6c81cc610130848154811061090e5761090e612989565b9060005260206000200160000160019054906101000a900461ffff16610130858154811061093e5761093e612989565b60009182526020909120015460405161095b929160ff16906129b8565b60405180910390a26101308054610974906001906129d9565b8154811061098457610984612989565b9060005260206000200161013083815481106109a2576109a2612989565b60009182526020909120825491018054909160ff169082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183818111156109ef576109ef61263d565b02179055508154815461ffff61010092839004169091027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff82168117835592546001600160a01b0363010000009182900416027fffffffffffffffffff0000000000000000000000000000000000000000ffffff9093167fffffffffffffffffff00000000000000000000000000000000000000000000ff90911617919091179055610130805480610aa357610aa36129f0565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffff00000000000000000000000000000000000000000000001690550190555b610b046116a5565b50505050565b610b12611515565b610b33604051806060016040528060348152602001612d13603491396115d9565b60005b81811015610df5576000838383818110610b5257610b52612989565b905060600201803603810190610b689190612a4e565b9050610b77816040015161156e565b61013054600090815b81811015610ca55760006101308281548110610b9e57610b9e612989565b6000918252602090912001805490915060ff166001811115610bc257610bc261263d565b85516001811115610bd557610bd561263d565b148015610bfa575060408501518154630100000090046001600160a01b039081169116145b15610c9c5760408581015182546020880151885193516001600160a01b03909316937fa682db621f4ae1c92cd6c492151d32fe657fc6db6e87bd65eb8bda05311f6ef293610c5393610100900461ffff16929190612aee565b60405180910390a26020850151815461ffff909116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff90911617905560019250610ca5565b50600101610b80565b5081610de75761013080546001818101835560009290925284517f2f605e086faac1d93117bbfbc18835d434e9405fadc1ca66faf4b864746daf349091018054869391929183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115610d2057610d2061263d565b021790555060208281015182546040948501517fffffffffffffffffff00000000000000000000000000000000000000000000ff90911661010061ffff909316929092027fffffffffffffffffff0000000000000000000000000000000000000000ffffff169190911763010000006001600160a01b03928316021790925585830151908601518651935191909216927f8c96910d818618d8b1de4e1b5672a192443e87aa553f0ebe4c47f9d8c928b28292610dde929091906129b8565b60405180910390a25b836001019350505050610b36565b50610dfe6116a5565b61013054610e0b9061187d565b610e15600160c955565b5050565b610e216113c5565b610e2b60006118c7565b565b60655433906001600160a01b03168114610eb45760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61040f816118c7565b610ec56113c5565b610ece8161156e565b61012d546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b61013054600090815b8181101561105b5760006101308281548110610f6b57610f6b612989565b906000526020600020019050866001811115610f8957610f8961263d565b815460ff166001811115610f9f57610f9f61263d565b148015610fbf575080546001600160a01b03878116630100000090920416145b15611052576001600160a01b03808916600090815261012e60209081526040808320938916835292905290812081896001811115610fff57610fff61263d565b60018111156110105761101061263d565b815260208101919091526040016000205482549091506127109061103d90610100900461ffff1683612b0a565b6110479190612b47565b94505050505061105e565b50600101610f4d565b50505b949350505050565b61013054600090815b81811015611152576000610130828154811061108d5761108d612989565b60009182526020909120604080516060810190915291018054829060ff1660018111156110bc576110bc61263d565b60018111156110cd576110cd61263d565b81529054610100810461ffff166020830152630100000090046001600160a01b03908116604092830152908201519192508781169116148015611132575084600181111561111d5761111d61263d565b815160018111156111305761113061263d565b145b15611149576020015161ffff169250611155915050565b5060010161106f565b50505b92915050565b600054610100900460ff161580801561117b5750600054600160ff909116105b806111955750303b158015611195575060005460ff166001145b6112075760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610eab565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561126557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61126e836118f8565b611276611986565b61127f82611a0b565b801561078357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b6112ee6113c5565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556113376033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b611377611515565b60005b818110156113ba576113b28484848481811061139857611398612989565b90506020020160208101906113ad91906125a8565b611ac0565b60010161137a565b50610783600160c955565b6033546001600160a01b03163314610e2b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610eab565b6001600160a01b03811661149b5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610eab565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091015b60405180910390a15050565b600260c954036115675760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610eab565b600260c955565b6001600160a01b03811661040f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008260018111156115c4576115c461263d565b036115cd575060005b919050565b600160c955565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906116259033908690600401612bf8565b602060405180830381865afa158015611642573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166691906128bd565b905080610e15573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610eab93929190612c1a565b60006116b2600180612944565b905060008167ffffffffffffffff8111156116cf576116cf612a1f565b6040519080825280602002602001820160405280156116f8578160200160208202803683370190505b506101305490915060005b818110156117e1576000610130828154811061172157611721612989565b60009182526020909120604080516060810190915291018054829060ff1660018111156117505761175061263d565b60018111156117615761176161263d565b81529054610100810461ffff1660208084019190915263010000009091046001600160a01b0316604090920191909152810151815191925090859060018111156117ad576117ad61263d565b815181106117bd576117bd612989565b602002602001018181516117d19190612c4f565b61ffff1690525050600101611703565b5060005b83811015610b045761271061ffff1683828151811061180657611806612989565b602002602001015161ffff161415801561183e575082818151811061182d5761182d612989565b602002602001015161ffff16600014155b15611875576040517f0b8ad7f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016117e5565b60fb5481111561040f5760fb546040517ff257f636000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610eab565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561040f81612099565b600054610100900460ff166119755760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b61197d612103565b61040f81612188565b600054610100900460ff16611a035760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b612205565b60fb548111611a825760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d60448201527f69740000000000000000000000000000000000000000000000000000000000006064820152608401610eab565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa9101611509565b6000611acd600180612944565b905060008167ffffffffffffffff811115611aea57611aea612a1f565b604051908082528060200260200182016040528015611b13578160200160208202803683370190505b5090506000805b83811015611bdb576001600160a01b03808716600090815261012e60209081526040808320938916835292905290812090826001811115611b5d57611b5d61263d565b6001811115611b6e57611b6e61263d565b6001811115611b7f57611b7f61263d565b815260200190815260200160002054838281518110611ba057611ba0612989565b602002602001018181525050828181518110611bbe57611bbe612989565b602002602001015182611bd19190612944565b9150600101611b1a565b5080600003611beb575050505050565b60008367ffffffffffffffff811115611c0657611c06612a1f565b604051908082528060200260200182016040528015611c2f578160200160208202803683370190505b50905060005b61013054811015611e645760006101308281548110611c5657611c56612989565b60009182526020909120604080516060810190915291018054829060ff166001811115611c8557611c8561263d565b6001811115611c9657611c9661263d565b81529054610100810461ffff90811660208085019190915263010000009092046001600160a01b0316604090930192909252820151825192935060009261271092919091169088906001811115611cef57611cef61263d565b81518110611cff57611cff612989565b6020026020010151611d119190612b0a565b611d1b9190612b47565b9050808483600001516001811115611d3557611d3561263d565b81518110611d4557611d45612989565b60200260200101818151611d599190612944565b9052508015611e5a576040820151611d7c906001600160a01b038a169083612282565b60408083015190517faac59a750000000000000000000000000000000000000000000000000000000081526001600160a01b038b811660048301528a811660248301529091169063aac59a7590604401600060405180830381600087803b158015611de657600080fd5b505af1158015611dfa573d6000803e3d6000fd5b50505050876001600160a01b031682604001516001600160a01b03167f09f71e7b22d78540ee9a42f09917a9d62f46735cb0dfa70d6bab27866d9cb5008460000151856020015185604051611e5193929190612c75565b60405180910390a35b5050600101611c35565b5060008467ffffffffffffffff811115611e8057611e80612a1f565b604051908082528060200260200182016040528015611ea9578160200160208202803683370190505b50905060005b8581101561208f57828181518110611ec957611ec9612989565b6020026020010151858281518110611ee357611ee3612989565b6020026020010151611ef591906129d9565b828281518110611f0757611f07612989565b602002602001018181525050818181518110611f2557611f25612989565b6020908102919091018101516001600160a01b03808b16600090815261012e84526040808220928c1682529190935282209091836001811115611f6a57611f6a61263d565b6001811115611f7b57611f7b61263d565b6001811115611f8c57611f8c61263d565b815260200190815260200160002081905550828181518110611fb057611fb0612989565b602002602001015161012f6000896001600160a01b03166001600160a01b0316815260200190815260200160002054611fe991906129d9565b6001600160a01b03808916600081815261012f602052604090209290925589167f7d881f3d6246a6a2b97b121b8ba093c17497912c68e8b2bca6108528e91df3ca83600181111561203c5761203c61263d565b88858151811061204e5761204e612989565b602002602001015186868151811061206857612068612989565b602002602001015160405161207f93929190612c9a565b60405180910390a3600101611eaf565b5050505050505050565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166121805760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b612302565b600054610100900460ff166104065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b600054610100900460ff166115d25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610783908490612388565b600054610100900460ff1661237f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b336118c7565b60006123dd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124709092919063ffffffff16565b90508051600014806123fe5750808060200190518101906123fe91906128bd565b6107835760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610eab565b606061105e848460008585600080866001600160a01b031685876040516124979190612cbb565b60006040518083038185875af1925050503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b50915091506124ea878383876124f5565b979650505050505050565b6060831561256457825160000361255d576001600160a01b0385163b61255d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610eab565b508161105e565b61105e83838151156125795781518083602001fd5b8060405162461bcd60e51b8152600401610eab9190612cd7565b6001600160a01b038116811461040f57600080fd5b6000602082840312156125ba57600080fd5b81356125c581612593565b9392505050565b6002811061040f57600080fd5b6000806000606084860312156125ee57600080fd5b83356125f981612593565b9250602084013561260981612593565b91506040840135612619816125cc565b809150509250925092565b60006020828403121561263657600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061040f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b606081016126b08561266c565b93815261ffff9290921660208301526001600160a01b031660409091015290565b600080604083850312156126e457600080fd5b82356126ef816125cc565b915060208301356126ff81612593565b809150509250929050565b6000806020838503121561271d57600080fd5b823567ffffffffffffffff8082111561273557600080fd5b818501915085601f83011261274957600080fd5b81358181111561275857600080fd5b86602060608302850101111561276d57600080fd5b60209290920196919550909350505050565b6000806000806080858703121561279557600080fd5b84356127a081612593565b935060208501356127b0816125cc565b925060408501356127c081612593565b915060608501356127d081612593565b939692955090935050565b600080604083850312156127ee57600080fd5b82356127f981612593565b915060208301356126ff816125cc565b6000806040838503121561281c57600080fd5b823561282781612593565b946020939093013593505050565b60008060006040848603121561284a57600080fd5b833561285581612593565b9250602084013567ffffffffffffffff8082111561287257600080fd5b818601915086601f83011261288657600080fd5b81358181111561289557600080fd5b8760208260051b85010111156128aa57600080fd5b6020830194508093505050509250925092565b6000602082840312156128cf57600080fd5b815180151581146125c557600080fd5b6000602082840312156128f157600080fd5b81516125c581612593565b60006020828403121561290e57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561295757612957612915565b500190565b8381526060810161296c8461266c565b83602083015261297b8361266c565b826040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b61ffff83168152604081016129cc8361266c565b8260208301529392505050565b6000828210156129eb576129eb612915565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060608284031215612a6057600080fd5b6040516060810181811067ffffffffffffffff82111715612aaa577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528235612ab8816125cc565b8152602083013561ffff81168114612acf57600080fd5b60208201526040830135612ae281612593565b60408201529392505050565b61ffff8481168252831660208201526060810161297b8361266c565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612b4257612b42612915565b500290565b600082612b7d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015612b9d578181015183820152602001612b85565b83811115610b045750506000910152565b60008151808452612bc6816020860160208601612b82565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b038316815260406020820152600061105e6040830184612bae565b60006001600160a01b03808616835280851660208401525060606040830152612c466060830184612bae565b95945050505050565b600061ffff808316818516808303821115612c6c57612c6c612915565b01949350505050565b60608101612c828561266c565b93815261ffff92909216602083015260409091015290565b60608101612ca78561266c565b938152602081019290925260409091015290565b60008251612ccd818460208701612b82565b9190910192915050565b6020815260006125c56020830184612bae56fe72656d6f7665446973747269627574696f6e436f6e66696728536368656d612c61646472657373296164644f72557064617465446973747269627574696f6e436f6e6669677328446973747269627574696f6e436f6e6669675b5d29a26469706673582212205eb79a0a3612b6adb45dcbc7d14826d2afd5547af534b542b9d4ebd2e2df21cb64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a35760003560e01c8063893ffe98116100ee578063b4a0bdf311610097578063e30c397811610071578063e30c3978146103a0578063f2fde38b146103b1578063fa7b81a0146103c4578063fc31116a146103eb57600080fd5b8063b4a0bdf314610373578063be26317e14610384578063cd6dc6871461038d57600080fd5b8063966961f0116100c8578063966961f01461032b578063aea211211461033e578063afcff50f1461035f57600080fd5b8063893ffe98146102e05780638da5cb5b146102f35780638dd950021461030457600080fd5b80634f429f3611610150578063715018a61161012a578063715018a6146102bd57806379ba5097146102c55780637b77cd6a146102cd57600080fd5b80634f429f36146102655780635db6da12146102785780635f3d6133146102aa57600080fd5b806316faecec1161018157806316faecec146101f157806333e1567f14610204578063392ee7121461024357600080fd5b80630e32cb86146101a85780631036bbe2146101bd578063163db71b146101de575b600080fd5b6101bb6101b63660046125a8565b6103fe565b005b6101c661271081565b60405161ffff90911681526020015b60405180910390f35b610130545b6040519081526020016101d5565b6101bb6101ff3660046125d9565b610412565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101d5565b610256610251366004612624565b610788565b6040516101d5939291906126a3565b6101bb6102733660046126d1565b6107c8565b6101e36102863660046125d9565b61012e60209081526000938452604080852082529284528284209052825290205481565b6101bb6102b836600461270a565b610b0a565b6101bb610e19565b6101bb610e2d565b6101bb6102db3660046125a8565b610ebd565b6101e36102ee36600461277f565b610f44565b6033546001600160a01b031661022b565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6101e36103393660046127db565b611066565b6101e361034c3660046125a8565b61012f6020526000908152604090205481565b61012d5461022b906001600160a01b031681565b6097546001600160a01b031661022b565b6101e360fb5481565b6101bb61039b366004612809565b61115b565b6065546001600160a01b031661022b565b6101bb6103bf3660046125a8565b6112e6565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6101bb6103f9366004612835565b61136f565b6104066113c5565b61040f8161141f565b50565b61041a611515565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610457573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047b91906128bd565b6104b1576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104ba8261156e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614158015610593575061012d546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015610564573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058891906128df565b6001600160a01b0316145b156105ca576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105d5826115ae565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038516906370a0823190602401602060405180830381865afa158015610638573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065c91906128fc565b6001600160a01b038516600090815261012f602052604090205490915080821115610776576001600160a01b03808716600090815261012e602090815260408083209389168352929052908120828403918291908660018111156106c2576106c261263d565b60018111156106d3576106d361263d565b815260200190815260200160002060008282546106f09190612944565b90915550506001600160a01b038616600090815261012f60205260408120805483929061071e908490612944565b92505081905550856001600160a01b0316876001600160a01b03167fa46b2431e663cf7b50c9d5129aff85d2394ecfd447b7ccba83986510a9d945ea83888860405161076c9392919061295c565b60405180910390a3505b505050610783600160c955565b505050565b610130818154811061079957600080fd5b60009182526020909120015460ff81169150610100810461ffff1690630100000090046001600160a01b031683565b6107e9604051806060016040528060288152602001612ceb602891396115d9565b600080805b61013054811015610894576000610130828154811061080f5761080f612989565b6000918252602090912001805490915060ff1660018111156108335761083361263d565b8660018111156108455761084561263d565b148015610865575080546001600160a01b03868116630100000090920416145b801561087957508054610100900461ffff16155b1561088b576001925081935050610894565b506001016107ee565b508015610afc5761013082815481106108af576108af612989565b9060005260206000200160000160039054906101000a90046001600160a01b03166001600160a01b03167f70e7a210881df49522a5bf05d477e00d59e52a41c96c1eedeaeb356b9e6c81cc610130848154811061090e5761090e612989565b9060005260206000200160000160019054906101000a900461ffff16610130858154811061093e5761093e612989565b60009182526020909120015460405161095b929160ff16906129b8565b60405180910390a26101308054610974906001906129d9565b8154811061098457610984612989565b9060005260206000200161013083815481106109a2576109a2612989565b60009182526020909120825491018054909160ff169082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183818111156109ef576109ef61263d565b02179055508154815461ffff61010092839004169091027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff82168117835592546001600160a01b0363010000009182900416027fffffffffffffffffff0000000000000000000000000000000000000000ffffff9093167fffffffffffffffffff00000000000000000000000000000000000000000000ff90911617919091179055610130805480610aa357610aa36129f0565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffff00000000000000000000000000000000000000000000001690550190555b610b046116a5565b50505050565b610b12611515565b610b33604051806060016040528060348152602001612d13603491396115d9565b60005b81811015610df5576000838383818110610b5257610b52612989565b905060600201803603810190610b689190612a4e565b9050610b77816040015161156e565b61013054600090815b81811015610ca55760006101308281548110610b9e57610b9e612989565b6000918252602090912001805490915060ff166001811115610bc257610bc261263d565b85516001811115610bd557610bd561263d565b148015610bfa575060408501518154630100000090046001600160a01b039081169116145b15610c9c5760408581015182546020880151885193516001600160a01b03909316937fa682db621f4ae1c92cd6c492151d32fe657fc6db6e87bd65eb8bda05311f6ef293610c5393610100900461ffff16929190612aee565b60405180910390a26020850151815461ffff909116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff90911617905560019250610ca5565b50600101610b80565b5081610de75761013080546001818101835560009290925284517f2f605e086faac1d93117bbfbc18835d434e9405fadc1ca66faf4b864746daf349091018054869391929183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115610d2057610d2061263d565b021790555060208281015182546040948501517fffffffffffffffffff00000000000000000000000000000000000000000000ff90911661010061ffff909316929092027fffffffffffffffffff0000000000000000000000000000000000000000ffffff169190911763010000006001600160a01b03928316021790925585830151908601518651935191909216927f8c96910d818618d8b1de4e1b5672a192443e87aa553f0ebe4c47f9d8c928b28292610dde929091906129b8565b60405180910390a25b836001019350505050610b36565b50610dfe6116a5565b61013054610e0b9061187d565b610e15600160c955565b5050565b610e216113c5565b610e2b60006118c7565b565b60655433906001600160a01b03168114610eb45760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61040f816118c7565b610ec56113c5565b610ece8161156e565b61012d546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b61013054600090815b8181101561105b5760006101308281548110610f6b57610f6b612989565b906000526020600020019050866001811115610f8957610f8961263d565b815460ff166001811115610f9f57610f9f61263d565b148015610fbf575080546001600160a01b03878116630100000090920416145b15611052576001600160a01b03808916600090815261012e60209081526040808320938916835292905290812081896001811115610fff57610fff61263d565b60018111156110105761101061263d565b815260208101919091526040016000205482549091506127109061103d90610100900461ffff1683612b0a565b6110479190612b47565b94505050505061105e565b50600101610f4d565b50505b949350505050565b61013054600090815b81811015611152576000610130828154811061108d5761108d612989565b60009182526020909120604080516060810190915291018054829060ff1660018111156110bc576110bc61263d565b60018111156110cd576110cd61263d565b81529054610100810461ffff166020830152630100000090046001600160a01b03908116604092830152908201519192508781169116148015611132575084600181111561111d5761111d61263d565b815160018111156111305761113061263d565b145b15611149576020015161ffff169250611155915050565b5060010161106f565b50505b92915050565b600054610100900460ff161580801561117b5750600054600160ff909116105b806111955750303b158015611195575060005460ff166001145b6112075760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610eab565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561126557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61126e836118f8565b611276611986565b61127f82611a0b565b801561078357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b6112ee6113c5565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556113376033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b611377611515565b60005b818110156113ba576113b28484848481811061139857611398612989565b90506020020160208101906113ad91906125a8565b611ac0565b60010161137a565b50610783600160c955565b6033546001600160a01b03163314610e2b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610eab565b6001600160a01b03811661149b5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610eab565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091015b60405180910390a15050565b600260c954036115675760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610eab565b600260c955565b6001600160a01b03811661040f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008260018111156115c4576115c461263d565b036115cd575060005b919050565b600160c955565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906116259033908690600401612bf8565b602060405180830381865afa158015611642573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166691906128bd565b905080610e15573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610eab93929190612c1a565b60006116b2600180612944565b905060008167ffffffffffffffff8111156116cf576116cf612a1f565b6040519080825280602002602001820160405280156116f8578160200160208202803683370190505b506101305490915060005b818110156117e1576000610130828154811061172157611721612989565b60009182526020909120604080516060810190915291018054829060ff1660018111156117505761175061263d565b60018111156117615761176161263d565b81529054610100810461ffff1660208084019190915263010000009091046001600160a01b0316604090920191909152810151815191925090859060018111156117ad576117ad61263d565b815181106117bd576117bd612989565b602002602001018181516117d19190612c4f565b61ffff1690525050600101611703565b5060005b83811015610b045761271061ffff1683828151811061180657611806612989565b602002602001015161ffff161415801561183e575082818151811061182d5761182d612989565b602002602001015161ffff16600014155b15611875576040517f0b8ad7f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016117e5565b60fb5481111561040f5760fb546040517ff257f636000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610eab565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561040f81612099565b600054610100900460ff166119755760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b61197d612103565b61040f81612188565b600054610100900460ff16611a035760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b612205565b60fb548111611a825760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d60448201527f69740000000000000000000000000000000000000000000000000000000000006064820152608401610eab565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa9101611509565b6000611acd600180612944565b905060008167ffffffffffffffff811115611aea57611aea612a1f565b604051908082528060200260200182016040528015611b13578160200160208202803683370190505b5090506000805b83811015611bdb576001600160a01b03808716600090815261012e60209081526040808320938916835292905290812090826001811115611b5d57611b5d61263d565b6001811115611b6e57611b6e61263d565b6001811115611b7f57611b7f61263d565b815260200190815260200160002054838281518110611ba057611ba0612989565b602002602001018181525050828181518110611bbe57611bbe612989565b602002602001015182611bd19190612944565b9150600101611b1a565b5080600003611beb575050505050565b60008367ffffffffffffffff811115611c0657611c06612a1f565b604051908082528060200260200182016040528015611c2f578160200160208202803683370190505b50905060005b61013054811015611e645760006101308281548110611c5657611c56612989565b60009182526020909120604080516060810190915291018054829060ff166001811115611c8557611c8561263d565b6001811115611c9657611c9661263d565b81529054610100810461ffff90811660208085019190915263010000009092046001600160a01b0316604090930192909252820151825192935060009261271092919091169088906001811115611cef57611cef61263d565b81518110611cff57611cff612989565b6020026020010151611d119190612b0a565b611d1b9190612b47565b9050808483600001516001811115611d3557611d3561263d565b81518110611d4557611d45612989565b60200260200101818151611d599190612944565b9052508015611e5a576040820151611d7c906001600160a01b038a169083612282565b60408083015190517faac59a750000000000000000000000000000000000000000000000000000000081526001600160a01b038b811660048301528a811660248301529091169063aac59a7590604401600060405180830381600087803b158015611de657600080fd5b505af1158015611dfa573d6000803e3d6000fd5b50505050876001600160a01b031682604001516001600160a01b03167f09f71e7b22d78540ee9a42f09917a9d62f46735cb0dfa70d6bab27866d9cb5008460000151856020015185604051611e5193929190612c75565b60405180910390a35b5050600101611c35565b5060008467ffffffffffffffff811115611e8057611e80612a1f565b604051908082528060200260200182016040528015611ea9578160200160208202803683370190505b50905060005b8581101561208f57828181518110611ec957611ec9612989565b6020026020010151858281518110611ee357611ee3612989565b6020026020010151611ef591906129d9565b828281518110611f0757611f07612989565b602002602001018181525050818181518110611f2557611f25612989565b6020908102919091018101516001600160a01b03808b16600090815261012e84526040808220928c1682529190935282209091836001811115611f6a57611f6a61263d565b6001811115611f7b57611f7b61263d565b6001811115611f8c57611f8c61263d565b815260200190815260200160002081905550828181518110611fb057611fb0612989565b602002602001015161012f6000896001600160a01b03166001600160a01b0316815260200190815260200160002054611fe991906129d9565b6001600160a01b03808916600081815261012f602052604090209290925589167f7d881f3d6246a6a2b97b121b8ba093c17497912c68e8b2bca6108528e91df3ca83600181111561203c5761203c61263d565b88858151811061204e5761204e612989565b602002602001015186868151811061206857612068612989565b602002602001015160405161207f93929190612c9a565b60405180910390a3600101611eaf565b5050505050505050565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166121805760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b612302565b600054610100900460ff166104065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b600054610100900460ff166115d25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610783908490612388565b600054610100900460ff1661237f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b336118c7565b60006123dd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124709092919063ffffffff16565b90508051600014806123fe5750808060200190518101906123fe91906128bd565b6107835760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610eab565b606061105e848460008585600080866001600160a01b031685876040516124979190612cbb565b60006040518083038185875af1925050503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b50915091506124ea878383876124f5565b979650505050505050565b6060831561256457825160000361255d576001600160a01b0385163b61255d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610eab565b508161105e565b61105e83838151156125795781518083602001fd5b8060405162461bcd60e51b8152600401610eab9190612cd7565b6001600160a01b038116811461040f57600080fd5b6000602082840312156125ba57600080fd5b81356125c581612593565b9392505050565b6002811061040f57600080fd5b6000806000606084860312156125ee57600080fd5b83356125f981612593565b9250602084013561260981612593565b91506040840135612619816125cc565b809150509250925092565b60006020828403121561263657600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061040f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b606081016126b08561266c565b93815261ffff9290921660208301526001600160a01b031660409091015290565b600080604083850312156126e457600080fd5b82356126ef816125cc565b915060208301356126ff81612593565b809150509250929050565b6000806020838503121561271d57600080fd5b823567ffffffffffffffff8082111561273557600080fd5b818501915085601f83011261274957600080fd5b81358181111561275857600080fd5b86602060608302850101111561276d57600080fd5b60209290920196919550909350505050565b6000806000806080858703121561279557600080fd5b84356127a081612593565b935060208501356127b0816125cc565b925060408501356127c081612593565b915060608501356127d081612593565b939692955090935050565b600080604083850312156127ee57600080fd5b82356127f981612593565b915060208301356126ff816125cc565b6000806040838503121561281c57600080fd5b823561282781612593565b946020939093013593505050565b60008060006040848603121561284a57600080fd5b833561285581612593565b9250602084013567ffffffffffffffff8082111561287257600080fd5b818601915086601f83011261288657600080fd5b81358181111561289557600080fd5b8760208260051b85010111156128aa57600080fd5b6020830194508093505050509250925092565b6000602082840312156128cf57600080fd5b815180151581146125c557600080fd5b6000602082840312156128f157600080fd5b81516125c581612593565b60006020828403121561290e57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561295757612957612915565b500190565b8381526060810161296c8461266c565b83602083015261297b8361266c565b826040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b61ffff83168152604081016129cc8361266c565b8260208301529392505050565b6000828210156129eb576129eb612915565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060608284031215612a6057600080fd5b6040516060810181811067ffffffffffffffff82111715612aaa577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528235612ab8816125cc565b8152602083013561ffff81168114612acf57600080fd5b60208201526040830135612ae281612593565b60408201529392505050565b61ffff8481168252831660208201526060810161297b8361266c565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612b4257612b42612915565b500290565b600082612b7d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015612b9d578181015183820152602001612b85565b83811115610b045750506000910152565b60008151808452612bc6816020860160208601612b82565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b038316815260406020820152600061105e6040830184612bae565b60006001600160a01b03808616835280851660208401525060606040830152612c466060830184612bae565b95945050505050565b600061ffff808316818516808303821115612c6c57612c6c612915565b01949350505050565b60608101612c828561266c565b93815261ffff92909216602083015260409091015290565b60608101612ca78561266c565b938152602081019290925260409091015290565b60008251612ccd818460208701612b82565b9190910192915050565b6020815260006125c56020830184612bae56fe72656d6f7665446973747269627574696f6e436f6e66696728536368656d612c61646472657373296164644f72557064617465446973747269627574696f6e436f6e6669677328446973747269627574696f6e436f6e6669675b5d29a26469706673582212205eb79a0a3612b6adb45dcbc7d14826d2afd5547af534b542b9d4ebd2e2df21cb64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptOwnership()": { + "details": "The new owner accepts the ownership transfer." + }, + "addOrUpdateDistributionConfigs((uint8,uint16,address)[])": { + "details": "Add or update destination targets based on destination address", + "params": { + "configs": "configurations of the destinations." + } + }, + "constructor": { + "custom:oz-upgrades-unsafe-allow": "constructor" + }, + "getPercentageDistribution(address,uint8)": { + "details": "Used to find out the percentage distribution for a particular destination based on schema", + "params": { + "destination": "the destination address of the distribution target", + "schema": "the schema of the distribution target" + }, + "returns": { + "_0": "percentage percentage distribution" + } + }, + "getUnreleasedFunds(address,uint8,address,address)": { + "details": "Used to find out the amount of funds that's going to be released when release funds is called.", + "params": { + "asset": "the asset address which will be released", + "comptroller": "the comptroller address of the pool", + "destination": "the destination address of the distribution target", + "schema": "the schema of the distribution target" + } + }, + "initialize(address,uint256)": { + "details": "Initializes the deployer to owner.", + "params": { + "_accessControlManager": "The address of ACM contract", + "_loopsLimit": "Limit for the loops in the contract to avoid DOS" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pendingOwner()": { + "details": "Returns the address of the pending owner." + }, + "releaseFunds(address,address[])": { + "details": "Release funds", + "params": { + "assets": "assets to be released to distribution targets", + "comptroller": "the comptroller address of the pool" + } + }, + "removeDistributionConfig(uint8,address)": { + "details": "Remove destionation target if percentage is 0", + "params": { + "destination": "destination address of the configuration", + "schema": "schema of the configuration" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setAccessControlManager(address)": { + "custom:access": "Only Governance", + "custom:event": "Emits NewAccessControlManager event", + "details": "Admin function to set address of AccessControlManager", + "params": { + "accessControlManager_": "The new address of the AccessControlManager" + } + }, + "setPoolRegistry(address)": { + "custom:error": "ZeroAddressNotAllowed is thrown when pool registry address is zero", + "details": "Pool registry setter.", + "params": { + "_poolRegistry": "Address of the pool registry" + } + }, + "totalDistributions()": { + "details": "Returns the total number of distribution targets" + }, + "transferOwnership(address)": { + "details": "Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner." + }, + "updateAssetsState(address,address,uint8)": { + "details": "Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.", + "params": { + "asset": "Asset address.", + "comptroller": "Comptroller address (pool)", + "incomeType": "type of income" + } + } + }, + "stateVariables": { + "CORE_POOL_COMPTROLLER": { + "custom:oz-upgrades-unsafe-allow": "state-variable-immutable" + }, + "WBNB": { + "custom:oz-upgrades-unsafe-allow": "state-variable-immutable" + }, + "vBNB": { + "custom:oz-upgrades-unsafe-allow": "state-variable-immutable" + } + }, + "version": 1 + }, + "userdoc": { + "errors": { + "MaxLoopsLimitExceeded(uint256,uint256)": [ + { + "notice": "Thrown an error on maxLoopsLimit exceeds for any loop" + } + ], + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ], + "ZeroAddressNotAllowed()": [ + { + "notice": "Thrown if the supplied address is a zero address where it is not allowed" + } + ] + }, + "events": { + "AssetReleased(address,address,uint8,uint256,uint256)": { + "notice": "Event emitted when an asset is released to a target" + }, + "AssetsReservesUpdated(address,address,uint256,uint8,uint8)": { + "notice": "Event emitted after updating of the assets reserves." + }, + "DistributionConfigAdded(address,uint16,uint8)": { + "notice": "Event emitted when distribution configuration is added" + }, + "DistributionConfigRemoved(address,uint16,uint8)": { + "notice": "Event emitted when distribution configuration is removed" + }, + "DistributionConfigUpdated(address,uint16,uint16,uint8)": { + "notice": "Event emitted when distribution configuration is updated" + }, + "MaxLoopsLimitUpdated(uint256,uint256)": { + "notice": "Emitted when max loops limit is set" + }, + "NewAccessControlManager(address,address)": { + "notice": "Emitted when access control manager contract address is changed" + }, + "PoolRegistryUpdated(address,address)": { + "notice": "Emitted when pool registry address is updated" + }, + "ReservesUpdated(address,address,uint8,uint256,uint256)": { + "notice": "Event emitted when asset reserves state is updated" + } + }, + "kind": "user", + "methods": { + "CORE_POOL_COMPTROLLER()": { + "notice": "address of core pool comptroller contract" + }, + "WBNB()": { + "notice": "address of WBNB contract" + }, + "accessControlManager()": { + "notice": "Returns the address of the access control manager contract" + }, + "assetsReserves(address,address,uint8)": { + "notice": "comptroller => asset => schema => balance" + }, + "distributionTargets(uint256)": { + "notice": "configuration for different income distribution targets" + }, + "poolRegistry()": { + "notice": "address of pool registry contract" + }, + "setAccessControlManager(address)": { + "notice": "Sets the address of AccessControlManager" + }, + "totalAssetReserve(address)": { + "notice": "asset => balance" + }, + "vBNB()": { + "notice": "address of vBNB contract" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 244, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 247, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1478, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 116, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 236, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 25, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_pendingOwner", + "offset": 0, + "slot": "101", + "type": "t_address" + }, + { + "astId": 104, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 4921, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_accessControlManager", + "offset": 0, + "slot": "151", + "type": "t_contract(IAccessControlManagerV8)5106" + }, + { + "astId": 4926, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 547, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_status", + "offset": 0, + "slot": "201", + "type": "t_uint256" + }, + { + "astId": 616, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 6066, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "maxLoopsLimit", + "offset": 0, + "slot": "251", + "type": "t_uint256" + }, + { + "astId": 6071, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 6465, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "poolRegistry", + "offset": 0, + "slot": "301", + "type": "t_address" + }, + { + "astId": 6478, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "assetsReserves", + "offset": 0, + "slot": "302", + "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_enum(Schema)6444,t_uint256)))" + }, + { + "astId": 6483, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "totalAssetReserve", + "offset": 0, + "slot": "303", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 6488, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "distributionTargets", + "offset": 0, + "slot": "304", + "type": "t_array(t_struct(DistributionConfig)6453_storage)dyn_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(DistributionConfig)6453_storage)dyn_storage": { + "base": "t_struct(DistributionConfig)6453_storage", + "encoding": "dynamic_array", + "label": "struct ProtocolShareReserve.DistributionConfig[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IAccessControlManagerV8)5106": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_enum(Schema)6444": { + "encoding": "inplace", + "label": "enum ProtocolShareReserve.Schema", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_mapping(t_address,t_mapping(t_enum(Schema)6444,t_uint256)))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => mapping(enum ProtocolShareReserve.Schema => uint256)))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_mapping(t_enum(Schema)6444,t_uint256))" + }, + "t_mapping(t_address,t_mapping(t_enum(Schema)6444,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(enum ProtocolShareReserve.Schema => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_enum(Schema)6444,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_enum(Schema)6444,t_uint256)": { + "encoding": "mapping", + "key": "t_enum(Schema)6444", + "label": "mapping(enum ProtocolShareReserve.Schema => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_struct(DistributionConfig)6453_storage": { + "encoding": "inplace", + "label": "struct ProtocolShareReserve.DistributionConfig", + "members": [ + { + "astId": 6447, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "schema", + "offset": 0, + "slot": "0", + "type": "t_enum(Schema)6444" + }, + { + "astId": 6450, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "percentage", + "offset": 1, + "slot": "0", + "type": "t_uint16" + }, + { + "astId": 6452, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "destination", + "offset": 3, + "slot": "0", + "type": "t_address" + } + ], + "numberOfBytes": "32" + }, + "t_uint16": { + "encoding": "inplace", + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} diff --git a/deployments/ethereum/ProtocolShareReserve_Proxy.json b/deployments/ethereum/ProtocolShareReserve_Proxy.json new file mode 100644 index 00000000..32060942 --- /dev/null +++ b/deployments/ethereum/ProtocolShareReserve_Proxy.json @@ -0,0 +1,277 @@ +{ + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "receipt": { + "to": null, + "from": "0x0Fd46ceD479C35d3116553Ae2DF190648CFD19Dd", + "contractAddress": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "transactionIndex": 69, + "gasUsed": "842949", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000000000000000000002000000000000000000000008000000000000000000000000000000002000001000000000002000000000800000000000000020000000000000000000800000080800001000000000000000000400000000000000000000000000000000080000000000080000000000000800000000000000000000000002000000400000000000100800000000000000000000000000020000000000000000001040000000000000400000800000000000020000000000200000000000000000000000000000800000000000000000000000000", + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc", + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "logs": [ + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000ee934792431b4ebd91591a86c884a8b49ed494c2" + ], + "data": "0x", + "logIndex": 85, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + }, + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000fd46ced479c35d3116553ae2df190648cfd19dd" + ], + "data": "0x", + "logIndex": 86, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + }, + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 87, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + }, + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014", + "logIndex": 88, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + }, + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 89, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + }, + { + "transactionIndex": 69, + "blockNumber": 19081788, + "transactionHash": "0xf83705ecad2bc0eaf1127ed1d46c3100819aad212dca06f9020b67952e96eee6", + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000567e4cc5e085d09f66f836fa8279f38b4e5866b9", + "logIndex": 90, + "blockHash": "0x57d761854f89a34105014d9f20acd8a31a9f6ef946178812b657ad0ea3d3d2bc" + } + ], + "blockNumber": 19081788, + "cumulativeGasUsed": "4625878", + "status": 1, + "byzantium": true + }, + "args": [ + "0xee934792431B4Ebd91591a86c884A8b49Ed494C2", + "0x567e4cc5e085d09f66f836fa8279f38b4e5866b9", + "0xcd6dc68700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000014" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/ethereum/solcInputs/0e89febeebc7444140de8e67c9067d2c.json b/deployments/ethereum/solcInputs/0e89febeebc7444140de8e67c9067d2c.json new file mode 100644 index 00000000..557e5cb0 --- /dev/null +++ b/deployments/ethereum/solcInputs/0e89febeebc7444140de8e67c9067d2c.json @@ -0,0 +1,78 @@ +{ + "language": "Solidity", + "sources": { + "solc_0.8/openzeppelin/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 (address initialOwner) {\n _transferOwnership(initialOwner);\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" + }, + "solc_0.8/openzeppelin/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" + }, + "solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n\n constructor (address initialOwner) Ownable(initialOwner) {}\n\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n TransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n */\n function changeAdmin(address newAdmin) external virtual ifAdmin {\n _changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internall call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overriden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view virtual returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(Address.isContract(IBeacon(newBeacon).implementation()), \"ERC1967: beacon implementation is not a contract\");\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "solc_0.8/openzeppelin/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "solc_0.8/openzeppelin/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract OptimizedTransparentUpgradeableProxy is ERC1967Proxy {\n address internal immutable _ADMIN;\n\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _ADMIN = admin_;\n\n // still store it to work with EIP-1967\n bytes32 slot = _ADMIN_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(slot, admin_)\n }\n emit AdminChanged(address(0), admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n\n function _getAdmin() internal view virtual override returns (address) {\n return _ADMIN;\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate that the this implementation remains valid after an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeTo(address newImplementation) external virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n}\n" + }, + "solc_0.8/openzeppelin/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() initializer {}\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\n // contract may have been reentered.\n require(_initializing ? _isConstructor() : !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} modifier, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n function _isConstructor() private view returns (bool) {\n return !Address.isContract(address(this));\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/beacon/UpgradeableBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../../access/Ownable.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\n * implementation contract, which is where they will delegate all function calls.\n *\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\n */\ncontract UpgradeableBeacon is IBeacon, Ownable {\n address private _implementation;\n\n /**\n * @dev Emitted when the implementation returned by the beacon is changed.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\n * beacon.\n */\n\n constructor(address implementation_, address initialOwner) Ownable(initialOwner) {\n _setImplementation(implementation_);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function implementation() public view virtual override returns (address) {\n return _implementation;\n }\n\n /**\n * @dev Upgrades the beacon to a new implementation.\n *\n * Emits an {Upgraded} event.\n *\n * Requirements:\n *\n * - msg.sender must be the owner of the contract.\n * - `newImplementation` must be a contract.\n */\n function upgradeTo(address newImplementation) public virtual onlyOwner {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation contract address for this beacon\n *\n * Requirements:\n *\n * - `newImplementation` must be a contract.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"UpgradeableBeacon: implementation is not a contract\");\n _implementation = newImplementation;\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/beacon/BeaconProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/BeaconProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../Proxy.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.\n *\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\n * conflict with the storage layout of the implementation behind the proxy.\n *\n * _Available since v3.4._\n */\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the proxy with `beacon`.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\n * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity\n * constructor.\n *\n * Requirements:\n *\n * - `beacon` must be a contract with the interface {IBeacon}.\n */\n constructor(address beacon, bytes memory data) payable {\n assert(_BEACON_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.beacon\")) - 1));\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n\n /**\n * @dev Returns the current beacon address.\n */\n function _beacon() internal view virtual returns (address) {\n return _getBeacon();\n }\n\n /**\n * @dev Returns the current implementation address of the associated beacon.\n */\n function _implementation() internal view virtual override returns (address) {\n return IBeacon(_getBeacon()).implementation();\n }\n\n /**\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\n *\n * Requirements:\n *\n * - `beacon` must be a contract.\n * - The implementation returned by `beacon` must be a contract.\n */\n function _setBeacon(address beacon, bytes memory data) internal virtual {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 999999 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/ethereum/solcInputs/6da26d3137c108aa956c278f90b592e2.json b/deployments/ethereum/solcInputs/6da26d3137c108aa956c278f90b592e2.json new file mode 100644 index 00000000..0fe7f223 --- /dev/null +++ b/deployments/ethereum/solcInputs/6da26d3137c108aa956c278f90b592e2.json @@ -0,0 +1,228 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides 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} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling 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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(account),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling 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/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1967.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967 {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../Proxy.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.\n *\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\n * conflict with the storage layout of the implementation behind the proxy.\n *\n * _Available since v3.4._\n */\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the proxy with `beacon`.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\n * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity\n * constructor.\n *\n * Requirements:\n *\n * - `beacon` must be a contract with the interface {IBeacon}.\n */\n constructor(address beacon, bytes memory data) payable {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n\n /**\n * @dev Returns the current beacon address.\n */\n function _beacon() internal view virtual returns (address) {\n return _getBeacon();\n }\n\n /**\n * @dev Returns the current implementation address of the associated beacon.\n */\n function _implementation() internal view virtual override returns (address) {\n return IBeacon(_getBeacon()).implementation();\n }\n\n /**\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\n *\n * Requirements:\n *\n * - `beacon` must be a contract.\n * - The implementation returned by `beacon` must be a contract.\n */\n function _setBeacon(address beacon, bytes memory data) internal virtual {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../../access/Ownable.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\n * implementation contract, which is where they will delegate all function calls.\n *\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\n */\ncontract UpgradeableBeacon is IBeacon, Ownable {\n address private _implementation;\n\n /**\n * @dev Emitted when the implementation returned by the beacon is changed.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\n * beacon.\n */\n constructor(address implementation_) {\n _setImplementation(implementation_);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function implementation() public view virtual override returns (address) {\n return _implementation;\n }\n\n /**\n * @dev Upgrades the beacon to a new implementation.\n *\n * Emits an {Upgraded} event.\n *\n * Requirements:\n *\n * - msg.sender must be the owner of the contract.\n * - `newImplementation` must be a contract.\n */\n function upgradeTo(address newImplementation) public virtual onlyOwner {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation contract address for this beacon\n *\n * Requirements:\n *\n * - `newImplementation` must be a contract.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"UpgradeableBeacon: implementation is not a contract\");\n _implementation = newImplementation;\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/IERC1967.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967Upgrade is IERC1967 {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\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 * 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 default value returned by this function, unless\n * it's 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(address from, address to, uint256 amount) 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 `from` to `to`.\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(address from, address to, uint256 amount) 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 // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\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 unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\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 // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\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(address owner, address spender, uint256 amount) 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(address owner, address spender, uint256 amount) 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(address from, address to, uint256 amount) 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(address from, address to, uint256 amount) 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.9.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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\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/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlledV8\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\n /// @notice Access control manager contract\n IAccessControlManagerV8 private _accessControlManager;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when access control manager contract address is changed\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n /// @notice Thrown when the action is prohibited by AccessControlManager\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Sets the address of AccessControlManager\n * @dev Admin function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n * @custom:event Emits NewAccessControlManager event\n * @custom:access Only Governance\n */\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Returns the address of the access control manager contract\n */\n function accessControlManager() external view returns (IAccessControlManagerV8) {\n return _accessControlManager;\n }\n\n /**\n * @dev Internal function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n */\n function _setAccessControlManager(address accessControlManager_) internal {\n require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n address oldAccessControlManager = address(_accessControlManager);\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title IAccessControlManagerV8\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\n */\ninterface IAccessControlManagerV8 is IAccessControl {\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) external;\n\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface OracleInterface {\n function getPrice(address asset) external view returns (uint256);\n}\n\ninterface ResilientOracleInterface is OracleInterface {\n function updatePrice(address vToken) external;\n\n function updateAssetPrice(address asset) external;\n\n function getUnderlyingPrice(address vToken) external view returns (uint256);\n}\n\ninterface TwapInterface is OracleInterface {\n function updateTwap(address asset) external returns (uint256);\n}\n\ninterface BoundValidatorInterface {\n function validatePriceWithAnchorPrice(\n address asset,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface VBep20Interface is IERC20Metadata {\n /**\n * @notice Underlying asset for this VToken\n */\n function underlying() external view returns (address);\n}\n" + }, + "@venusprotocol/oracle/contracts/ResilientOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"./interfaces/VBep20Interface.sol\";\nimport \"./interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ResilientOracle\n * @author Venus\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\n * \n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\n * for attacking the protocol.\n * \n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\n * \n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \n * \n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\n * market. The upper bound ratio represents the deviation between reported price (the price that’s being\n * validated) and the anchor price (the price we are validating against) above which the reported price will\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\n * should be true:\n\n```\nanchorRatio = anchorPrice/reporterPrice\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\n```\n\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \n * \n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\n * oracle to be stagnant and treat it like it's disabled.\n */\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\n /**\n * @dev Oracle roles:\n * **main**: The most trustworthy price source\n * **pivot**: Price oracle used as a loose sanity checker\n * **fallback**: The backup source when main oracle price is invalidated\n */\n enum OracleRole {\n MAIN,\n PIVOT,\n FALLBACK\n }\n\n struct TokenConfig {\n /// @notice asset address\n address asset;\n /// @notice `oracles` stores the oracles based on their role in the following order:\n /// [main, pivot, fallback],\n /// It can be indexed with the corresponding enum OracleRole value\n address[3] oracles;\n /// @notice `enableFlagsForOracles` stores the enabled state\n /// for each oracle in the same order as `oracles`\n bool[3] enableFlagsForOracles;\n }\n\n uint256 public constant INVALID_PRICE = 0;\n\n /// @notice Native market address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable nativeMarket;\n\n /// @notice VAI address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vai;\n\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\n /// and can serve as any underlying asset of a market that supports native tokens\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Bound validator contract address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n BoundValidatorInterface public immutable boundValidator;\n\n mapping(address => TokenConfig) private tokenConfigs;\n\n event TokenConfigAdded(\n address indexed asset,\n address indexed mainOracle,\n address indexed pivotOracle,\n address fallbackOracle\n );\n\n /// Event emitted when an oracle is set\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\n\n /// Event emitted when an oracle is enabled or disabled\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\n\n /**\n * @notice Checks whether an address is null or not\n */\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /**\n * @notice Checks whether token config exists by checking whether asset is null address\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\n * @param asset asset address\n */\n modifier checkTokenConfigExistence(address asset) {\n if (tokenConfigs[asset].asset == address(0)) revert(\"token config must exist\");\n _;\n }\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\n /// (e.g vETH on ethereum would not be supported, only vWETH)\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\n /// Set to address(0) of VAI is not existent.\n /// @param _boundValidator Address of the bound validator contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address nativeMarketAddress,\n address vaiAddress,\n BoundValidatorInterface _boundValidator\n ) notNullAddress(address(_boundValidator)) {\n nativeMarket = nativeMarketAddress;\n vai = vaiAddress;\n boundValidator = _boundValidator;\n\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract admin and sets the BoundValidator contract address\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n }\n\n /**\n * @notice Pauses oracle\n * @custom:access Only Governance\n */\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n _pause();\n }\n\n /**\n * @notice Unpauses oracle\n * @custom:access Only Governance\n */\n function unpause() external {\n _checkAccessAllowed(\"unpause()\");\n _unpause();\n }\n\n /**\n * @notice Batch sets token configs\n * @param tokenConfigs_ Token config array\n * @custom:access Only Governance\n * @custom:error Throws a length error if the length of the token configs array is 0\n */\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\n if (tokenConfigs_.length == 0) revert(\"length can't be 0\");\n uint256 numTokenConfigs = tokenConfigs_.length;\n for (uint256 i; i < numTokenConfigs; ) {\n setTokenConfig(tokenConfigs_[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Sets oracle for a given asset and role.\n * @dev Supplied asset **must** exist and main oracle may not be null\n * @param asset Asset address\n * @param oracle Oracle address\n * @param role Oracle role\n * @custom:access Only Governance\n * @custom:error Null address error if main-role oracle address is null\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\n */\n function setOracle(\n address asset,\n address oracle,\n OracleRole role\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"setOracle(address,address,uint8)\");\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\"can't set zero address to main oracle\");\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\n emit OracleSet(asset, oracle, uint256(role));\n }\n\n /**\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\n * @param asset Asset address\n * @param role Oracle role\n * @param enable Enabled boolean of the oracle\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n */\n function enableOracle(\n address asset,\n OracleRole role,\n bool enable\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"enableOracle(address,uint8,bool)\");\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\n emit OracleEnabled(asset, uint256(role), enable);\n }\n\n /**\n * @notice Updates the TWAP pivot oracle price.\n * @dev This function should always be called before calling getUnderlyingPrice\n * @param vToken vToken address\n */\n function updatePrice(address vToken) external override {\n address asset = _getUnderlyingAsset(vToken);\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @notice Updates the pivot oracle price. Currently using TWAP\n * @dev This function should always be called before calling getPrice\n * @param asset asset address\n */\n function updateAssetPrice(address asset) external {\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @dev Gets token config by asset address\n * @param asset asset address\n * @return tokenConfig Config for the asset\n */\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\n return tokenConfigs[asset];\n }\n\n /**\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\n * - Check if the oracle is paused globally\n * - Validate price from main oracle against pivot oracle\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\n * - Validate price from main oracle against fallback oracle if the second validation failed\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\n * main oracle price is returned.\n * @param vToken vToken address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n\n address asset = _getUnderlyingAsset(vToken);\n return _getPrice(asset);\n }\n\n /**\n * @notice Gets price of the asset\n * @param asset asset address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getPrice(address asset) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n return _getPrice(asset);\n }\n\n /**\n * @notice Sets/resets single token configs.\n * @dev main oracle **must not** be a null address\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress is thrown if asset address is null\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(\n tokenConfig.asset,\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\n );\n }\n\n /**\n * @notice Gets oracle and enabled status by asset address\n * @param asset asset address\n * @param role Oracle role\n * @return oracle Oracle address based on role\n * @return enabled Enabled flag of the oracle based on token config\n */\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\n oracle = tokenConfigs[asset].oracles[uint256(role)];\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\n }\n\n function _getPrice(address asset) internal view returns (uint256) {\n uint256 pivotPrice = INVALID_PRICE;\n\n // Get pivot oracle price, Invalid price if not available or error\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracleEnabled && pivotOracle != address(0)) {\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\n pivotPrice = pricePivot;\n } catch {}\n }\n\n // Compare main price and pivot price, return main price and if validation was successful\n // note: In case pivot oracle is not available but main price is available and\n // validation is successful, the main oracle price is returned.\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\n asset,\n pivotPrice,\n pivotOracleEnabled && pivotOracle != address(0)\n );\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\n\n // Compare fallback and pivot if main oracle comparision fails with pivot\n // Return fallback price when fallback price is validated successfully with pivot oracle\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\n\n // Lastly compare main price and fallback price\n if (\n mainPrice != INVALID_PRICE &&\n fallbackPrice != INVALID_PRICE &&\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\n ) {\n return mainPrice;\n }\n\n revert(\"invalid resilient oracle price\");\n }\n\n /**\n * @notice Gets a price for the provided asset\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\n * able to fetch a correct price\n * @param asset asset address\n * @param pivotPrice Pivot oracle price\n * @param pivotEnabled If pivot oracle is not empty and enabled\n * @return price USD price in scaled decimals\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\n * @return pivotValidated Boolean representing if the validation of main oracle price\n * and pivot oracle price were successful\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\n * address is null\n */\n function _getMainOraclePrice(\n address asset,\n uint256 pivotPrice,\n bool pivotEnabled\n ) internal view returns (uint256, bool) {\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\n if (mainOracleEnabled && mainOracle != address(0)) {\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\n if (!pivotEnabled) {\n return (mainOraclePrice, true);\n }\n if (pivotPrice == INVALID_PRICE) {\n return (mainOraclePrice, false);\n }\n return (\n mainOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\n * @param asset asset address\n * @return price USD price in 18 decimals\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\n * and pivot oracle price were successfull\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\n * address is null\n */\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\n if (fallbackEnabled && fallbackOracle != address(0)) {\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\n if (pivotPrice == INVALID_PRICE) {\n return (fallbackOraclePrice, false);\n }\n return (\n fallbackOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function returns the underlying asset of a vToken\n * @param vToken vToken address\n * @return asset underlying asset address\n */\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\n if (vToken == nativeMarket) {\n asset = NATIVE_TOKEN_ADDR;\n } else if (vToken == vai) {\n asset = vai;\n } else {\n asset = VBep20Interface(vToken).underlying();\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\nuint256 constant EXP_SCALE = 1e18;\n\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\nuint256 constant MANTISSA_ONE = EXP_SCALE;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\n" + }, + "@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title MaxLoopsLimitHelper\n * @author Venus\n * @notice Abstract contract used to avoid collection with too many items that would generate gas errors and DoS.\n */\nabstract contract MaxLoopsLimitHelper {\n // Limit for the loops to avoid the DOS\n uint256 public maxLoopsLimit;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when max loops limit is set\n event MaxLoopsLimitUpdated(uint256 oldMaxLoopsLimit, uint256 newmaxLoopsLimit);\n\n /// @notice Thrown an error on maxLoopsLimit exceeds for any loop\n error MaxLoopsLimitExceeded(uint256 loopsLimit, uint256 requiredLoops);\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function _setMaxLoopsLimit(uint256 limit) internal {\n require(limit > maxLoopsLimit, \"Comptroller: Invalid maxLoopsLimit\");\n\n uint256 oldMaxLoopsLimit = maxLoopsLimit;\n maxLoopsLimit = limit;\n\n emit MaxLoopsLimitUpdated(oldMaxLoopsLimit, limit);\n }\n\n /**\n * @notice Compare the maxLoopsLimit with number of the times loop iterate\n * @param len Length of the loops iterate\n * @custom:error MaxLoopsLimitExceeded error is thrown when loops length exceeds maxLoopsLimit\n */\n function _ensureMaxLoops(uint256 len) internal view {\n if (len > maxLoopsLimit) {\n revert MaxLoopsLimitExceeded(maxLoopsLimit, len);\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/validators.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\nerror ZeroAddressNotAllowed();\n\n/// @notice Thrown if the supplied value is 0 where it is not allowed\nerror ZeroValueNotAllowed();\n\n/// @notice Checks if the provided address is nonzero, reverts otherwise\n/// @param address_ Address to check\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\nfunction ensureNonzeroAddress(address address_) pure {\n if (address_ == address(0)) {\n revert ZeroAddressNotAllowed();\n }\n}\n\n/// @notice Checks if the provided value is nonzero, reverts otherwise\n/// @param value_ Value to check\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\nfunction ensureNonzeroValue(uint256 value_) pure {\n if (value_ == 0) {\n revert ZeroValueNotAllowed();\n }\n}\n" + }, + "contracts/Interfaces/IComptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IComptroller {\n function isComptroller() external view returns (bool);\n\n function markets(address) external view returns (bool);\n\n function getAllMarkets() external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IConverterNetwork.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAbstractTokenConverter } from \"../TokenConverter/IAbstractTokenConverter.sol\";\n\n/**\n * @title IConverterNetwork\n * @author Venus\n * @notice Interface implemented by `ConverterNetwork`.\n */\ninterface IConverterNetwork {\n /// @notice Adds new converter to the array\n /// @param _tokenConverter Address of the token converter\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Removes converter from the array\n /// @param _tokenConverter Address of the token converter\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice This function returns the array containing all the converters addresses\n /// @return Array containing all the converters addresses\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\n\n /// @notice This function checks for given address is converter or not\n /// @param _tokenConverter Address of the token converter\n /// @return boolean true if given address is converter otherwise false\n function isTokenConverter(address _tokenConverter) external view returns (bool);\n}\n" + }, + "contracts/Interfaces/IIncomeDestination.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IIncomeDestination {\n function updateAssetsState(address comptroller, address asset) external;\n}\n" + }, + "contracts/Interfaces/IPoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IPoolRegistry {\n /// @notice Get VToken in the Pool for an Asset\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\n\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION\n }\n\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) external;\n}\n" + }, + "contracts/Interfaces/IRiskFund.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IRiskFund\n * @author Venus\n * @notice Interface implemented by `RiskFund`.\n */\ninterface IRiskFund {\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updatePoolState(\n address comptroller,\n address asset,\n uint256 amount\n ) external;\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n\n/**\n * @title IRiskFundGetters\n * @author Venus\n * @notice Interface implemented by `RiskFund` for getter methods.\n */\ninterface IRiskFundGetters {\n function convertibleBaseAsset() external view returns (address);\n}\n" + }, + "contracts/Interfaces/IRiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IRiskFundConverter {\n function updateAssetsState(address comptroller, address asset) external;\n\n function getPools(address asset) external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IShortfall.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IShortfall\n * @author Venus\n * @notice Interface implemented by `Shortfall`.\n */\ninterface IShortfall {\n function convertibleBaseAsset() external returns (address);\n}\n" + }, + "contracts/Interfaces/IVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IVToken {\n function underlying() external view returns (address);\n}\n" + }, + "contracts/Interfaces/IXVSVault.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @title IXVSVaultProxy\n/// @author Venus\n/// @notice Interface implemented by `XVSVault`.\ninterface IXVSVault {\n function xvsStore() external view returns (address);\n}\n" + }, + "contracts/ProtocolReserve/ProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IProtocolShareReserve } from \"../Interfaces/IProtocolShareReserve.sol\";\nimport { IComptroller } from \"../Interfaces/IComptroller.sol\";\nimport { IPoolRegistry } from \"../Interfaces/IPoolRegistry.sol\";\nimport { IVToken } from \"../Interfaces/IVToken.sol\";\nimport { IIncomeDestination } from \"../Interfaces/IIncomeDestination.sol\";\n\nerror InvalidAddress();\nerror UnsupportedAsset();\nerror InvalidTotalPercentage();\nerror InvalidMaxLoopsLimit();\n\ncontract ProtocolShareReserve is\n AccessControlledV8,\n ReentrancyGuardUpgradeable,\n MaxLoopsLimitHelper,\n IProtocolShareReserve\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice protocol income is categorized into two schemas.\n /// The first schema is for spread income\n /// The second schema is for liquidation income\n enum Schema {\n PROTOCOL_RESERVES,\n ADDITIONAL_REVENUE\n }\n\n struct DistributionConfig {\n Schema schema;\n /// @dev percenatge is represented without any scale\n uint16 percentage;\n address destination;\n }\n\n /// @notice address of core pool comptroller contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n /// @notice address of WBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable WBNB;\n\n /// @notice address of vBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vBNB;\n\n /// @notice address of pool registry contract\n address public poolRegistry;\n\n uint16 public constant MAX_PERCENT = 1e4;\n\n /// @notice comptroller => asset => schema => balance\n mapping(address => mapping(address => mapping(Schema => uint256))) public assetsReserves;\n\n /// @notice asset => balance\n mapping(address => uint256) public totalAssetReserve;\n\n /// @notice configuration for different income distribution targets\n DistributionConfig[] public distributionTargets;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Event emitted after updating of the assets reserves.\n event AssetsReservesUpdated(\n address indexed comptroller,\n address indexed asset,\n uint256 amount,\n IncomeType incomeType,\n Schema schema\n );\n\n /// @notice Event emitted when an asset is released to a target\n event AssetReleased(\n address indexed destination,\n address indexed asset,\n Schema schema,\n uint256 percent,\n uint256 amount\n );\n\n /// @notice Event emitted when asset reserves state is updated\n event ReservesUpdated(\n address indexed comptroller,\n address indexed asset,\n Schema schema,\n uint256 oldBalance,\n uint256 newBalance\n );\n\n /// @notice Event emitted when distribution configuration is updated\n event DistributionConfigUpdated(\n address indexed destination,\n uint16 oldPercentage,\n uint16 newPercentage,\n Schema schema\n );\n\n /// @notice Event emitted when distribution configuration is added\n event DistributionConfigAdded(address indexed destination, uint16 percentage, Schema schema);\n\n /// @notice Event emitted when distribution configuration is removed\n event DistributionConfigRemoved(address indexed destination, uint16 percentage, Schema schema);\n\n /**\n * @dev Constructor to initialize the immutable variables\n * @param _corePoolComptroller The address of core pool comptroller\n * @param _wbnb The address of WBNB\n * @param _vbnb The address of vBNB\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _corePoolComptroller,\n address _wbnb,\n address _vbnb\n ) {\n ensureNonzeroAddress(_corePoolComptroller);\n ensureNonzeroAddress(_wbnb);\n ensureNonzeroAddress(_vbnb);\n\n CORE_POOL_COMPTROLLER = _corePoolComptroller;\n WBNB = _wbnb;\n vBNB = _vbnb;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @dev Initializes the deployer to owner.\n * @param _accessControlManager The address of ACM contract\n * @param _loopsLimit Limit for the loops in the contract to avoid DOS\n */\n function initialize(address _accessControlManager, uint256 _loopsLimit) external initializer {\n __AccessControlled_init(_accessControlManager);\n __ReentrancyGuard_init();\n _setMaxLoopsLimit(_loopsLimit);\n }\n\n /**\n * @dev Pool registry setter.\n * @param _poolRegistry Address of the pool registry\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n */\n function setPoolRegistry(address _poolRegistry) external onlyOwner {\n ensureNonzeroAddress(_poolRegistry);\n emit PoolRegistryUpdated(poolRegistry, _poolRegistry);\n poolRegistry = _poolRegistry;\n }\n\n /**\n * @dev Add or update destination targets based on destination address\n * @param configs configurations of the destinations.\n */\n function addOrUpdateDistributionConfigs(DistributionConfig[] calldata configs) external nonReentrant {\n _checkAccessAllowed(\"addOrUpdateDistributionConfigs(DistributionConfig[])\");\n\n for (uint256 i = 0; i < configs.length; ) {\n DistributionConfig memory _config = configs[i];\n ensureNonzeroAddress(_config.destination);\n\n bool updated = false;\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 j = 0; j < distributionTargetsLength; ) {\n DistributionConfig storage config = distributionTargets[j];\n\n if (_config.schema == config.schema && config.destination == _config.destination) {\n emit DistributionConfigUpdated(\n _config.destination,\n config.percentage,\n _config.percentage,\n _config.schema\n );\n config.percentage = _config.percentage;\n updated = true;\n break;\n }\n\n unchecked {\n ++j;\n }\n }\n\n if (!updated) {\n distributionTargets.push(_config);\n emit DistributionConfigAdded(_config.destination, _config.percentage, _config.schema);\n }\n\n unchecked {\n ++i;\n }\n }\n\n _ensurePercentages();\n _ensureMaxLoops(distributionTargets.length);\n }\n\n /**\n * @dev Remove destionation target if percentage is 0\n * @param schema schema of the configuration\n * @param destination destination address of the configuration\n */\n function removeDistributionConfig(Schema schema, address destination) external {\n _checkAccessAllowed(\"removeDistributionConfig(Schema,address)\");\n\n uint256 distributionIndex;\n bool found = false;\n for (uint256 i = 0; i < distributionTargets.length; ) {\n DistributionConfig storage config = distributionTargets[i];\n\n if (schema == config.schema && destination == config.destination && config.percentage == 0) {\n found = true;\n distributionIndex = i;\n break;\n }\n\n unchecked {\n ++i;\n }\n }\n\n if (found) {\n emit DistributionConfigRemoved(\n distributionTargets[distributionIndex].destination,\n distributionTargets[distributionIndex].percentage,\n distributionTargets[distributionIndex].schema\n );\n\n distributionTargets[distributionIndex] = distributionTargets[distributionTargets.length - 1];\n distributionTargets.pop();\n }\n\n _ensurePercentages();\n }\n\n /**\n * @dev Release funds\n * @param comptroller the comptroller address of the pool\n * @param assets assets to be released to distribution targets\n */\n function releaseFunds(address comptroller, address[] calldata assets) external nonReentrant {\n for (uint256 i = 0; i < assets.length; ) {\n _releaseFund(comptroller, assets[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Used to find out the amount of funds that's going to be released when release funds is called.\n * @param comptroller the comptroller address of the pool\n * @param schema the schema of the distribution target\n * @param destination the destination address of the distribution target\n * @param asset the asset address which will be released\n */\n function getUnreleasedFunds(\n address comptroller,\n Schema schema,\n address destination,\n address asset\n ) external view returns (uint256) {\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\n DistributionConfig storage _config = distributionTargets[i];\n if (_config.schema == schema && _config.destination == destination) {\n uint256 total = assetsReserves[comptroller][asset][schema];\n return (total * _config.percentage) / MAX_PERCENT;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Returns the total number of distribution targets\n */\n function totalDistributions() external view returns (uint256) {\n return distributionTargets.length;\n }\n\n /**\n * @dev Used to find out the percentage distribution for a particular destination based on schema\n * @param destination the destination address of the distribution target\n * @param schema the schema of the distribution target\n * @return percentage percentage distribution\n */\n function getPercentageDistribution(address destination, Schema schema) external view returns (uint256) {\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\n DistributionConfig memory config = distributionTargets[i];\n\n if (config.destination == destination && config.schema == schema) {\n return config.percentage;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\n * @param comptroller Comptroller address (pool)\n * @param asset Asset address.\n * @param incomeType type of income\n */\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) public override(IProtocolShareReserve) nonReentrant {\n if (!IComptroller(comptroller).isComptroller()) revert InvalidAddress();\n ensureNonzeroAddress(asset);\n\n if (\n comptroller != CORE_POOL_COMPTROLLER &&\n IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) == address(0)\n ) revert InvalidAddress();\n\n Schema schema = _getSchema(incomeType);\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\n uint256 assetReserve = totalAssetReserve[asset];\n\n if (currentBalance > assetReserve) {\n uint256 balanceDifference;\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n\n assetsReserves[comptroller][asset][schema] += balanceDifference;\n totalAssetReserve[asset] += balanceDifference;\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference, incomeType, schema);\n }\n }\n\n /**\n * @dev asset from a particular pool to be release to distribution targets\n * @param comptroller Comptroller address(pool)\n * @param asset Asset address.\n */\n function _releaseFund(address comptroller, address asset) internal {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint256[] memory schemaBalances = new uint256[](totalSchemas);\n uint256 totalBalance;\n for (uint256 schemaValue; schemaValue < totalSchemas; ) {\n schemaBalances[schemaValue] = assetsReserves[comptroller][asset][Schema(schemaValue)];\n totalBalance += schemaBalances[schemaValue];\n\n unchecked {\n ++schemaValue;\n }\n }\n\n if (totalBalance == 0) {\n return;\n }\n\n uint256[] memory totalTransferAmounts = new uint256[](totalSchemas);\n for (uint256 i = 0; i < distributionTargets.length; ) {\n DistributionConfig memory _config = distributionTargets[i];\n\n uint256 transferAmount = (schemaBalances[uint256(_config.schema)] * _config.percentage) / MAX_PERCENT;\n totalTransferAmounts[uint256(_config.schema)] += transferAmount;\n\n if (transferAmount != 0) {\n IERC20Upgradeable(asset).safeTransfer(_config.destination, transferAmount);\n IIncomeDestination(_config.destination).updateAssetsState(comptroller, asset);\n\n emit AssetReleased(_config.destination, asset, _config.schema, _config.percentage, transferAmount);\n }\n\n unchecked {\n ++i;\n }\n }\n\n uint256[] memory newSchemaBalances = new uint256[](totalSchemas);\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\n newSchemaBalances[schemaValue] = schemaBalances[schemaValue] - totalTransferAmounts[schemaValue];\n assetsReserves[comptroller][asset][Schema(schemaValue)] = newSchemaBalances[schemaValue];\n totalAssetReserve[asset] = totalAssetReserve[asset] - totalTransferAmounts[schemaValue];\n\n emit ReservesUpdated(\n comptroller,\n asset,\n Schema(schemaValue),\n schemaBalances[schemaValue],\n newSchemaBalances[schemaValue]\n );\n\n unchecked {\n ++schemaValue;\n }\n }\n }\n\n /**\n * @dev Returns the schema based on income type\n * @param incomeType type of income\n * @return schema schema for distribution\n */\n function _getSchema(IncomeType incomeType) internal view returns (Schema schema) {\n schema = Schema.ADDITIONAL_REVENUE;\n\n if (incomeType == IncomeType.SPREAD) {\n schema = Schema.PROTOCOL_RESERVES;\n }\n }\n\n /**\n * @dev This ensures that the total percentage of all the distribution targets is 100% or 0%\n */\n function _ensurePercentages() internal view {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint16[] memory totalPercentages = new uint16[](totalSchemas);\n\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\n DistributionConfig memory config = distributionTargets[i];\n totalPercentages[uint256(config.schema)] += config.percentage;\n\n unchecked {\n ++i;\n }\n }\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\n if (totalPercentages[schemaValue] != MAX_PERCENT && totalPercentages[schemaValue] != 0)\n revert InvalidTotalPercentage();\n\n unchecked {\n ++schemaValue;\n }\n }\n }\n\n /**\n * @dev Returns the underlying asset address for the vToken\n * @param vToken vToken address\n * @return asset address of asset\n */\n function _getUnderlying(address vToken) internal view returns (address) {\n if (vToken == vBNB) {\n return WBNB;\n } else {\n return IVToken(vToken).underlying();\n }\n }\n}\n" + }, + "contracts/ProtocolReserve/RiskFundStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\n\n/// @title ReserveHelpersStorage\n/// @author Venus\n/// @dev Reserve helpers storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract ReserveHelpersStorage is Ownable2StepUpgradeable {\n /// @notice Deprecated slot for assetReserves mapping\n bytes32 private __deprecatedSlot1;\n\n /// @notice Available asset's fund per pool in RiskFund\n /// Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) public poolAssetsFunds;\n\n /// @notice Deprecated slot for poolRegistry address\n bytes32 private __deprecatedSlot2;\n /// @notice Deprecated slot for status variable\n bytes32 private __deprecatedSlot3;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n uint256[46] private __gap;\n}\n\n/// @title MaxLoopsLimitHelpersStorage\n/// @author Venus\n/// @dev Max loop limit helpers storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract MaxLoopsLimitHelpersStorage {\n /// @notice Limit for the loops to avoid the DOS\n /// @notice This state is deprecated, using it to prevent storage collision\n uint256 public maxLoopsLimit;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n uint256[49] private __gap;\n}\n\n/// @title RiskFundV1Storage\n/// @author Venus\n/// @dev Risk fund V1 storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundV1Storage is ReserveHelpersStorage, MaxLoopsLimitHelpersStorage {\n /// @notice Address of base asset\n address public convertibleBaseAsset;\n /// @notice Address of shortfall contract\n address public shortfall;\n\n /// @notice This state is deprecated, using it to prevent storage collision\n address private pancakeSwapRouter;\n /// @notice This state is deprecated, using it to prevent storage collision\n uint256 private minAmountToConvert;\n}\n\n/// @title RiskFundV2Storage\n/// @author Venus\n/// @dev Risk fund V2 storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeable {\n /// @notice Risk fund converter address\n address public riskFundConverter;\n}\n" + }, + "contracts/ProtocolReserve/RiskFundV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IRiskFund } from \"../Interfaces/IRiskFund.sol\";\nimport { IRiskFundConverter } from \"../Interfaces/IRiskFundConverter.sol\";\nimport { RiskFundV2Storage } from \"./RiskFundStorage.sol\";\n\n/// @title RiskFundV2\n/// @author Venus\n/// @notice Contract with basic features to hold base asset for different Comptrollers\n/// @dev This contract does not support BNB\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Emitted when convertible base asset address is updated\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\n\n /// @notice Emitted when risk fund converter address is updated\n event RiskFundConverterUpdated(address indexed oldRiskFundConverter, address indexed newRiskFundConverter);\n\n /// @notice Emitted when shortfall contract address is updated\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\n\n /// @notice Emitted when reserves are transferred for auction\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\n\n /// @notice Emitted when pool asset states is updated with amount transferred to this contract\n event PoolAssetsIncreased(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\n event PoolAssetsDecreased(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Event emitted when tokens are swept\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /// @notice Event emitted when tokens are swept and transferred from pool\n event SweepTokenFromPool(address indexed token, address indexed comptroller, uint256 amount);\n\n /// @notice Error is thrown when updatePoolState is not called by riskFundConverter\n error InvalidRiskFundConverter();\n\n /// @notice Error is thrown when transferReserveForAuction is called by non shortfall address\n error InvalidShortfallAddress();\n\n /// @notice thrown when amount entered is greater than balance\n error InsufficientBalance();\n\n /// @notice Error is thrown when pool reserve is less than the amount needed\n error InsufficientPoolReserve(address comptroller, uint256 amount, uint256 poolReserve);\n\n /// @dev Convertible base asset setter\n /// @param convertibleBaseAsset_ Address of the convertible base asset\n /// @custom:event ConvertibleBaseAssetUpdated emit on success\n /// @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n /// @custom:access Only Governance\n function setConvertibleBaseAsset(address convertibleBaseAsset_) external onlyOwner {\n ensureNonzeroAddress(convertibleBaseAsset_);\n emit ConvertibleBaseAssetUpdated(convertibleBaseAsset, convertibleBaseAsset_);\n convertibleBaseAsset = convertibleBaseAsset_;\n }\n\n /// @dev Risk fund converter setter\n /// @param riskFundConverter_ Address of the risk fund converter\n /// @custom:event RiskFundConverterUpdated emit on success\n /// @custom:error ZeroAddressNotAllowed is thrown when risk fund converter address is zero\n /// @custom:access Only Governance\n function setRiskFundConverter(address riskFundConverter_) external onlyOwner {\n ensureNonzeroAddress(riskFundConverter_);\n emit RiskFundConverterUpdated(riskFundConverter, riskFundConverter_);\n riskFundConverter = riskFundConverter_;\n }\n\n /// @dev Shortfall contract address setter\n /// @param shortfallContractAddress_ Address of the auction contract\n /// @custom:event ShortfallContractUpdated emit on success\n /// @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n /// @custom:access Only Governance\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\n ensureNonzeroAddress(shortfallContractAddress_);\n emit ShortfallContractUpdated(shortfall, shortfallContractAddress_);\n shortfall = shortfallContractAddress_;\n }\n\n /// @dev Transfer tokens for auction to shortfall contract\n /// @param comptroller Comptroller of the pool\n /// @param amount Amount to be transferred to the shortfall\n /// @return Amount of tokens transferred to the shortfall\n /// @custom:event TransferredReserveForAuction emit on success\n /// @custom:error InvalidShortfallAddress is thrown when caller is not shortfall contract\n /// @custom:error InsufficientPoolReserve is thrown when pool reserve is less than the amount needed\n /// @custom:access Only Shortfall contract\n function transferReserveForAuction(address comptroller, uint256 amount)\n external\n override\n nonReentrant\n returns (uint256)\n {\n uint256 poolReserve = poolAssetsFunds[comptroller][convertibleBaseAsset];\n\n if (msg.sender != shortfall) {\n revert InvalidShortfallAddress();\n }\n if (amount > poolReserve) {\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\n }\n\n unchecked {\n poolAssetsFunds[comptroller][convertibleBaseAsset] = poolReserve - amount;\n }\n\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall, amount);\n emit TransferredReserveForAuction(comptroller, amount);\n\n return amount;\n }\n\n /// @notice Function to sweep baseAsset for pool, Tokens are sent to address(to)\n /// @param tokenAddress Address of the asset(token)\n /// @param to Address to which assets will be transferred\n /// @param amount Amount need to sweep for the pool\n /// @custom:event Emits SweepToken event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\n /// @custom:access Only Governance\n function sweepToken(\n address tokenAddress,\n address to,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(to);\n ensureNonzeroValue(amount);\n\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n preSweepToken(tokenAddress, amount);\n token.safeTransfer(to, amount);\n\n emit SweepToken(tokenAddress, to, amount);\n }\n\n /// @notice Function to sweep token from pool\n /// @param tokenAddress Address of the asset(token)\n /// @param comptroller Pool address to which assets will be transferred\n /// @param amount Amount need to sweep from the pool\n /// @custom:event Emits sweepTokenFromPool event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zero\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\n /// @custom:access Only Governance\n function sweepTokenFromPool(\n address tokenAddress,\n address comptroller,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(comptroller);\n ensureNonzeroValue(amount);\n\n uint256 poolReserve = poolAssetsFunds[comptroller][tokenAddress];\n\n if (amount > poolReserve) {\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\n }\n\n unchecked {\n poolAssetsFunds[comptroller][tokenAddress] = poolReserve - amount;\n }\n\n IERC20Upgradeable(tokenAddress).safeTransfer(comptroller, amount);\n\n emit SweepTokenFromPool(tokenAddress, comptroller, amount);\n }\n\n /**\n * @notice Get the Amount of the Base asset in the risk fund for the specific pool.\n * @param comptroller Comptroller address(pool).\n * @return Base Asset's reserve in risk fund.\n */\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256) {\n return poolAssetsFunds[comptroller][convertibleBaseAsset];\n }\n\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\n /// @param comptroller Comptroller address (pool)\n /// @param asset Address of the asset(token)\n /// @param amount Amount transferred for the pool\n /// @custom:event PoolAssetsIncreased emits on success\n /// @custom:error InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\n /// @custom:access Only RiskFundConverter contract\n function updatePoolState(\n address comptroller,\n address asset,\n uint256 amount\n ) public {\n if (msg.sender != riskFundConverter) {\n revert InvalidRiskFundConverter();\n }\n\n poolAssetsFunds[comptroller][asset] += amount;\n emit PoolAssetsIncreased(comptroller, asset, amount);\n }\n\n /// @dev Operations to perform before sweeping tokens\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\n function preSweepToken(address tokenAddress, uint256 amount) internal {\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\n if (amount > balance) revert InsufficientBalance();\n\n address[] memory pools = IRiskFundConverter(riskFundConverter).getPools(tokenAddress);\n\n uint256 assetReserves;\n uint256 poolsLength = pools.length;\n for (uint256 i; i < poolsLength; ) {\n assetReserves += poolAssetsFunds[pools[i]][tokenAddress];\n unchecked {\n ++i;\n }\n }\n\n uint256 balanceDiff = balance - assetReserves;\n\n if (balanceDiff < amount) {\n uint256 amountDiff;\n unchecked {\n amountDiff = amount - balanceDiff;\n }\n uint256 distributedShare;\n for (uint256 i; i < poolsLength; ) {\n if (poolAssetsFunds[pools[i]][tokenAddress] != 0) {\n uint256 poolAmountShare;\n if (i < (poolsLength - 1)) {\n poolAmountShare = (poolAssetsFunds[pools[i]][tokenAddress] * amount) / assetReserves;\n distributedShare += poolAmountShare;\n } else {\n poolAmountShare = amountDiff - distributedShare;\n }\n poolAssetsFunds[pools[i]][tokenAddress] -= poolAmountShare;\n emit PoolAssetsDecreased(pools[i], tokenAddress, poolAmountShare);\n }\n unchecked {\n ++i;\n }\n }\n }\n }\n}\n" + }, + "contracts/ProtocolReserve/XVSVaultTreasury.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IXVSVault } from \"../Interfaces/IXVSVault.sol\";\n\n/// @title XVSVaultTreasury\n/// @author Venus\n/// @notice XVSVaultTreasury stores the tokens sent by SingleTokenConverter(XVS) and funds XVSVault\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract XVSVaultTreasury is AccessControlledV8, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The xvs token address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable XVS_ADDRESS;\n\n /// @notice The xvsvault address\n address public xvsVault;\n\n /// @notice Emitted when XVS vault address is updated\n event XVSVaultUpdated(address indexed oldXVSVault, address indexed newXVSVault);\n\n /// @notice Emitted when funds transferred to XVSStore address\n event FundsTransferredToXVSStore(address indexed xvsStore, uint256 amountMantissa);\n\n /// @notice Thrown when given input amount is zero\n error InsufficientBalance();\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @param xvsAddress_ XVS token address\n constructor(address xvsAddress_) {\n ensureNonzeroAddress(xvsAddress_);\n XVS_ADDRESS = xvsAddress_;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param xvsVault_ XVSVault address\n /// @custom:event XVSVaultUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when XVS vault address is zero\n function initialize(address accessControlManager_, address xvsVault_) public initializer {\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n _setXVSVault(xvsVault_);\n }\n\n /// @dev XVS vault setter\n /// @param xvsVault_ Address of the XVS vault\n /// @custom:event XVSVaultUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when XVS vault address is zero\n function setXVSVault(address xvsVault_) external onlyOwner {\n _setXVSVault(xvsVault_);\n }\n\n /// @notice This function transfers funds to the XVS vault\n /// @param amountMantissa Amount to be sent to XVS vault\n /// @custom:event FundsTransferredToXVSStore emits on success\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\n /// @custom:access Restricted by ACM\n function fundXVSVault(uint256 amountMantissa) external nonReentrant {\n _checkAccessAllowed(\"fundXVSVault(uint256)\");\n ensureNonzeroValue(amountMantissa);\n\n uint256 balance = IERC20Upgradeable(XVS_ADDRESS).balanceOf(address(this));\n\n if (balance < amountMantissa) {\n revert InsufficientBalance();\n }\n\n address xvsStore = IXVSVault(xvsVault).xvsStore();\n ensureNonzeroAddress(xvsStore);\n IERC20Upgradeable(XVS_ADDRESS).safeTransfer(xvsStore, amountMantissa);\n\n emit FundsTransferredToXVSStore(xvsStore, amountMantissa);\n }\n\n /// @dev XVS vault setter\n /// @param xvsVault_ Address of the XVS vault\n /// @custom:event XVSVaultUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when XVS vault address is zero\n function _setXVSVault(address xvsVault_) internal {\n ensureNonzeroAddress(xvsVault_);\n emit XVSVaultUpdated(xvsVault, xvsVault_);\n xvsVault = xvsVault_;\n }\n}\n" + }, + "contracts/Test/imports.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n// This file is needed to make hardhat and typechain generate artifacts for\n// contracts we depend on (e.g. in tests or deployments) but not use directly.\n// Another way to do this would be to use hardhat-dependency-compiler, but\n// since we only have a couple of dependencies, installing a separate package\n// seems an overhead.\n\nimport { UpgradeableBeacon } from \"@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol\";\nimport { BeaconProxy } from \"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\";\n" + }, + "contracts/Test/Mocks/MockACM.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { AccessControl } from \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract MockACM is AccessControl {\n /// @notice Emitted when an account is given a permission to a certain contract function\n /// @dev If contract address is 0x000..0 this means that the account is a default admin of this function and\n /// can call any contract function with this signature\n event PermissionGranted(address account, address contractAddress, string functionSig);\n\n /// @notice Emitted when an account is revoked a permission to a certain contract function\n event PermissionRevoked(address account, address contractAddress, string functionSig);\n\n constructor() {\n // Grant the contract deployer the default admin role: it will be able\n // to grant and revoke any roles\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Gives a function call permission to one single account\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n * @param contractAddress address of contract for which call permissions will be granted\n * @dev if contractAddress is zero address, the account can access the specified function\n * on **any** contract managed by this ACL\n * @param functionSig signature e.g. \"functionName(uint256,bool)\"\n * @param accountToPermit account that will be given access to the contract function\n * @custom:event Emits a {RoleGranted} and {PermissionGranted} events.\n */\n function giveCallPermission(\n address contractAddress,\n string memory functionSig,\n address accountToPermit\n ) public {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n grantRole(role, accountToPermit);\n emit PermissionGranted(accountToPermit, contractAddress, functionSig);\n }\n\n /**\n * @notice Revokes an account's permission to a particular function call\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n * \t\tMay emit a {RoleRevoked} event.\n * @param contractAddress address of contract for which call permissions will be revoked\n * @param functionSig signature e.g. \"functionName(uint256,bool)\"\n * @custom:event Emits {RoleRevoked} and {PermissionRevoked} events.\n */\n function revokeCallPermission(\n address contractAddress,\n string memory functionSig,\n address accountToRevoke\n ) public {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n revokeRole(role, accountToRevoke);\n emit PermissionRevoked(accountToRevoke, contractAddress, functionSig);\n }\n\n /**\n * @notice Verifies if the given account can call a contract's guarded function\n * @dev Since restricted contracts using this function as a permission hook, we can get contracts address with msg.sender\n * @param account for which call permissions will be checked\n * @param functionSig restricted function signature e.g. \"functionName(uint256,bool)\"\n * @return false if the user account cannot call the particular contract function\n *\n */\n function isAllowedToCall(address account, string memory functionSig) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(msg.sender, functionSig));\n\n if (hasRole(role, account)) {\n return true;\n } else {\n role = keccak256(abi.encodePacked(address(0), functionSig));\n return hasRole(role, account);\n }\n }\n\n /**\n * @notice Verifies if the given account can call a contract's guarded function\n * @dev This function is used as a view function to check permissions rather than contract hook for access restriction check.\n * @param account for which call permissions will be checked against\n * @param contractAddress address of the restricted contract\n * @param functionSig signature of the restricted function e.g. \"functionName(uint256,bool)\"\n * @return false if the user account cannot call the particular contract function\n */\n function hasPermission(\n address account,\n address contractAddress,\n string memory functionSig\n ) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n return hasRole(role, account);\n }\n}\n" + }, + "contracts/Test/Mocks/MockArraySorter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\nimport { sort } from \"../../Utils/ArrayHelpers.sol\";\n\ncontract MockArraySorter {\n function sortArray(uint256[] memory balances, address[] memory addrs)\n external\n view\n returns (address[] memory, uint256[] memory)\n {\n sort(balances, addrs);\n return (addrs, balances);\n }\n}\n" + }, + "contracts/Test/Mocks/MockConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\n\nimport { AbstractTokenConverter } from \"../../TokenConverter/AbstractTokenConverter.sol\";\nimport { IRiskFundGetters } from \"../../Interfaces/IRiskFund.sol\";\n\ncontract MockConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) public assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) public poolsAssetsReserves;\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n function mockPrivateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 balanceDiff\n ) external {\n _privateConversion(comptroller, tokenAddressOut, balanceDiff);\n }\n\n function AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) public initializer {\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n assetsReserves[tokenAddressIn] += convertedTokenInBalance;\n poolsAssetsReserves[comptroller][tokenAddressIn] += convertedTokenInBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @notice Get base asset address\n function _getDestinationBaseAsset() internal view override returns (address) {\n return IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/Test/Mocks/MockDeflationaryToken.sol": { + "content": "pragma solidity 0.8.13;\n\ncontract MockDeflatingToken {\n string public constant NAME = \"Deflating Test Token\";\n string public constant SYMBOL = \"DTT\";\n uint8 public constant DECIMALS = 18;\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n mapping(address => mapping(address => uint256)) public allowance;\n\n bytes32 public immutable DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n event Approval(address indexed owner, address indexed spender, uint256 value);\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n constructor(uint256 _totalSupply) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string NAME,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(NAME)),\n keccak256(bytes(\"1\")),\n chainId,\n address(this)\n )\n );\n _mint(msg.sender, _totalSupply);\n }\n\n function approve(address spender, uint256 value) external returns (bool) {\n _approve(msg.sender, spender, value);\n return true;\n }\n\n function transfer(address to, uint256 value) external returns (bool) {\n _transfer(msg.sender, to, value);\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n ) external returns (bool) {\n if (allowance[from][msg.sender] != type(uint256).max) {\n allowance[from][msg.sender] = allowance[from][msg.sender] - value;\n }\n _transfer(from, to, value);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"EXPIRED\");\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNATURE\");\n _approve(owner, spender, value);\n }\n\n function _mint(address to, uint256 value) internal {\n totalSupply = totalSupply + value;\n balanceOf[to] = balanceOf[to] + value;\n emit Transfer(address(0), to, value);\n }\n\n function _burn(address from, uint256 value) internal {\n balanceOf[from] = balanceOf[from] - value;\n totalSupply = totalSupply - value;\n emit Transfer(from, address(0), value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n ) private {\n allowance[owner][spender] = value;\n emit Approval(owner, spender, value);\n }\n\n function _transfer(\n address from,\n address to,\n uint256 value\n ) private {\n uint256 burnAmount = value / 100;\n _burn(from, burnAmount);\n uint256 transferAmount = value - burnAmount;\n balanceOf[from] = balanceOf[from] - transferAmount;\n balanceOf[to] = balanceOf[to] + transferAmount;\n emit Transfer(from, to, transferAmount);\n }\n}\n" + }, + "contracts/Test/Mocks/MockRiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { RiskFundConverter } from \"../../TokenConverter/RiskFundConverter.sol\";\n\ncontract MockRiskFundConverter is RiskFundConverter {\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) RiskFundConverter(corePoolComptroller_, vBNB_, nativeWrapped_) {}\n\n function postConversionHookMock(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) external {\n super._postConversionHook(tokenInAddress, tokenOutAddress, amountIn, amountOut);\n }\n\n function preTransferHookMock(address tokenOutAddress, uint256 amountOut) external {\n super._preTransferHook(tokenOutAddress, amountOut);\n }\n\n function setAssetsReserves(address asset, uint256 amount) external {\n assetsReserves[asset] = amount;\n }\n\n function setPoolsAssetsReserves(\n address comptroller,\n address asset,\n uint256 amount\n ) external {\n poolsAssetsReserves[comptroller][asset] = amount;\n }\n\n function getPoolsAssetsReserves(address comptroller, address asset) external view returns (uint256) {\n return poolsAssetsReserves[comptroller][asset];\n }\n\n function getAssetsReserves(address asset) external view returns (uint256) {\n return assetsReserves[asset];\n }\n}\n" + }, + "contracts/Test/Mocks/MockToken.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 { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockToken is ERC20 {\n uint8 private immutable _decimals;\n\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) ERC20(name_, symbol_) {\n _decimals = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function allocateTo(address owner, uint256 amount) external {\n _mint(owner, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/TokenConverter/AbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { MANTISSA_ONE, EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\nimport { IAbstractTokenConverter } from \"./IAbstractTokenConverter.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @title AbstractTokenConverter\n/// @author Venus\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\n/*\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\n *\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\n * a. convertExactTokensSupportingFeeOnTransferTokens\n * b. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\n * similar to Case I.\n *\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * a. convertExactTokens\n * b. convertForExactTokens\n * c. convertExactTokensSupportingFeeOnTransferTokens\n * d. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * similar to Case III.\n *\n * ------------------------------------------------------------------------------------------------------------------------------------\n * Example 1:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInAmount - 100\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\n * function for tokenIn as deflationary token.\n *\n * Example 2:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\n * tokenOutAmount - 70\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\n * ------------------------------------------------------------------------------------------------------------------------------------\n *\n * This contract also supports private conversion between the converters:\n * Private conversions:\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\n *\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\n *\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\n * tokenAddressOut: As base asset of that converter.\n *\n * ConverterNetwork:\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\n * and tokenAddressOut provided.\n *\n * findTokenConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\n *\n * findTokenConvertersForConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\n */\n\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Maximum incentive could be\n uint256 public constant MAX_INCENTIVE = 0.5e18;\n\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\n uint256 public minAmountToConvert;\n\n /// @notice Venus price oracle contract\n ResilientOracle public priceOracle;\n\n /// @notice conversion configurations for the existing pairs\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\n\n /// @notice Address that all incoming tokens are transferred to\n address public destinationAddress;\n\n /// @notice Boolean for if conversion is paused\n bool public conversionPaused;\n\n /// @notice Address of the converterNetwork contract\n IConverterNetwork public converterNetwork;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n uint256[45] private __gap;\n\n /// @notice Emitted when config is updated for tokens pair\n event ConversionConfigUpdated(\n address indexed tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 oldIncentive,\n uint256 newIncentive,\n ConversionAccessibility oldAccess,\n ConversionAccessibility newAccess\n );\n /// @notice Emitted when price oracle address is updated\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\n\n /// @notice Emitted when destination address is updated\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\n\n /// @notice Emitted when converterNetwork address is updated\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\n\n /// @notice Emitted when exact amount of tokens are converted for tokens\n event ConvertedExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens\n event ConvertedForExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when conversion is paused\n event ConversionPaused(address indexed sender);\n\n /// @notice Emitted when conversion is unpaused\n event ConversionResumed(address indexed sender);\n\n /// @notice Event emitted when tokens are swept\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\n error AmountOutMismatched();\n\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\n error AmountInMismatched();\n\n /// @notice Thrown when given input amount is zero\n error InsufficientInputAmount();\n\n /// @notice Thrown when given output amount is zero\n error InsufficientOutputAmount();\n\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\n error ConversionConfigNotEnabled();\n\n /// @notice Thrown when conversion is enabled only for private conversions\n error ConversionEnabledOnlyForPrivateConversions();\n\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n error InvalidToAddress();\n\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\n\n /// @notice Thrown when amountOut is lower than amountOutMin\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\n\n /// @notice Thrown when amountIn is higher than amountInMax\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\n\n /// @notice Thrown when conversion is paused\n error ConversionTokensPaused();\n\n /// @notice Thrown when conversion is Active\n error ConversionTokensActive();\n\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\n error InvalidTokenConfigAddresses();\n\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\n error InsufficientPoolLiquidity();\n\n /// @notice When address of the ConverterNetwork is not set or Zero address\n error InvalidConverterNetwork();\n\n /// @notice Thrown when trying to set non zero incentive for private conversion\n error NonZeroIncentiveForPrivateConversion();\n\n /// @notice Thrown when using convertForExactTokens deflationary tokens\n error DeflationaryTokenNotSupported();\n\n /// @notice Thrown when minimum amount to convert is zero\n error InvalidMinimumAmountToConvert();\n\n /// @notice Thrown when there is a mismatch in the length of input arrays\n error InputLengthMisMatch();\n\n /**\n * @notice Modifier to ensure valid conversion parameters for a token conversion\n * and check if conversion is paused or not\n * @param to The recipient address for the converted tokens\n * @param tokenAddressIn The input token address for the conversion\n * @param tokenAddressOut The output token address for the conversion\n */\n modifier validConversionParameters(\n address to,\n address tokenAddressIn,\n address tokenAddressOut\n ) {\n _checkConversionPaused();\n ensureNonzeroAddress(to);\n if (to == tokenAddressIn || to == tokenAddressOut) {\n revert InvalidToAddress();\n }\n _;\n }\n\n /// @notice Pause conversion of tokens\n /// @custom:event Emits ConversionPaused on success\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\n /// @custom:access Restricted by ACM\n function pauseConversion() external {\n _checkAccessAllowed(\"pauseConversion()\");\n _checkConversionPaused();\n conversionPaused = true;\n emit ConversionPaused(msg.sender);\n }\n\n /// @notice Resume conversion of tokens.\n /// @custom:event Emits ConversionResumed on success\n /// @custom:error ConversionTokensActive thrown when conversion is already active\n /// @custom:access Restricted by ACM\n function resumeConversion() external {\n _checkAccessAllowed(\"resumeConversion()\");\n if (!conversionPaused) {\n revert ConversionTokensActive();\n }\n\n conversionPaused = false;\n emit ConversionResumed(msg.sender);\n }\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:access Only Governance\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\n _setPriceOracle(priceOracle_);\n }\n\n /// @notice Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:access Only Governance\n function setDestination(address destinationAddress_) external onlyOwner {\n _setDestination(destinationAddress_);\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:access Only Governance\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\n _setConverterNetwork(converterNetwork_);\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:access Only Governance\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n _setMinAmountToConvert(minAmountToConvert_);\n }\n\n /// @notice Batch sets the conversion configurations\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressesOut Array of addresses of tokenOut\n /// @param conversionConfigs Array of conversionConfig config details to update\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\n function setConversionConfigs(\n address tokenAddressIn,\n address[] calldata tokenAddressesOut,\n ConversionConfig[] calldata conversionConfigs\n ) external {\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\n\n for (uint256 i; i < tokenOutArrayLength; ) {\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountIn != amountInMantissa) {\n revert AmountInMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\n /// otherwise the amount is adjusted\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountOut != amountOutMantissa) {\n revert AmountOutMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\n /// @param tokenAddress The address of the ERC-20 token to sweep\n /// @param to The address to which tokens will be transferred\n /// @param amount The amount to transfer\n /// @custom:event Emits SweepToken event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\n /// @custom:access Only Governance\n function sweepToken(\n address tokenAddress,\n address to,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(to);\n ensureNonzeroValue(amount);\n\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n preSweepToken(tokenAddress, amount);\n token.safeTransfer(to, amount);\n\n emit SweepToken(tokenAddress, to, amount);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @dev This function retrieves values without altering token prices\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n amountConvertedMantissa = amountInMantissa;\n uint256 tokenInToOutConversion;\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountConvertedMantissa =\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\n tokenInToOutConversion; //round-up\n amountOutMantissa = maxTokenOutReserve;\n }\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @dev This function retrieves values without altering token prices\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountOutMantissa = maxTokenOutReserve;\n }\n\n amountConvertedMantissa = amountOutMantissa;\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountInMantissa;\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountOutMantissa;\n }\n\n /// @notice This method updated the states of this contract after getting funds from PSR\n /// after settling the amount(if any) through privateConversion between converters\n /// @dev This function is called by protocolShareReserve\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\n if (balanceDiff > 0) {\n _privateConversion(comptroller, asset, balanceDiff);\n }\n }\n\n /// @notice Set the configuration for new or existing conversion pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n /// @custom:event Emits ConversionConfigUpdated event on success\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\n /// @custom:access Controlled by AccessControlManager\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) public {\n _checkAccessAllowed(\"setConversionConfig(address,address,ConversionConfig)\");\n ensureNonzeroAddress(tokenAddressIn);\n ensureNonzeroAddress(tokenAddressOut);\n\n if (conversionConfig.incentive > MAX_INCENTIVE) {\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\n }\n\n if (\n (tokenAddressIn == tokenAddressOut) ||\n (tokenAddressIn != _getDestinationBaseAsset()) ||\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\n ) {\n revert InvalidTokenConfigAddresses();\n }\n\n if (\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\n conversionConfig.incentive != 0\n ) {\n revert NonZeroIncentiveForPrivateConversion();\n }\n\n if (\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\n (address(converterNetwork) == address(0))\n ) {\n revert InvalidConverterNetwork();\n }\n\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n emit ConversionConfigUpdated(\n tokenAddressIn,\n tokenAddressOut,\n configuration.incentive,\n conversionConfig.incentive,\n configuration.conversionAccess,\n conversionConfig.conversionAccess\n );\n\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\n } else {\n configuration.incentive = conversionConfig.incentive;\n configuration.conversionAccess = conversionConfig.conversionAccess;\n }\n }\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\n\n /// @dev Operations to perform before sweeping tokens\n /// @param token Address of the token\n /// @param amount Amount transferred to address(to)\n function preSweepToken(address token, uint256 amount) internal virtual {}\n\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function _convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n if (amountOutMantissa < amountOutMinMantissa) {\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n }\n\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\n /// it is called by convertForExactTokens function\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n if (actualAmountIn != amountInMantissa) {\n revert DeflationaryTokenNotSupported();\n }\n\n if (actualAmountIn > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n actualAmountOut = amountOutMantissa;\n }\n\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n if (amountInMantissa > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\n }\n\n /// @dev return actualAmountOut from reserves for tokenAddressOut\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\n function _doTransferOut(\n address tokenAddressOut,\n address to,\n uint256 amountConvertedMantissa\n ) internal {\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountConvertedMantissa) {\n revert InsufficientPoolLiquidity();\n }\n\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\n\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\n tokenOut.safeTransfer(to, amountConvertedMantissa);\n }\n\n /// @notice Transfer tokenAddressIn from user to destination\n /// @param tokenAddressIn Address of the token to convert\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @return actualAmountIn Actual amount transferred to destination\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\n }\n\n /// @dev Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:event Emits PriceOracleUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\n ensureNonzeroAddress(address(priceOracle_));\n emit PriceOracleUpdated(priceOracle, priceOracle_);\n priceOracle = priceOracle_;\n }\n\n /// @dev Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:event Emits DestinationAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\n function _setDestination(address destinationAddress_) internal {\n ensureNonzeroAddress(destinationAddress_);\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\n destinationAddress = destinationAddress_;\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\n ensureNonzeroAddress(address(converterNetwork_));\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\n converterNetwork = converterNetwork_;\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:event MinAmountToConvertUpdated is emitted in success\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\n ensureNonzeroValue(minAmountToConvert_);\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\n minAmountToConvert = minAmountToConvert_;\n }\n\n /// @dev Hook to perform after converting tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param amountIn Amount of tokenIn converted\n /// @param amountOut Amount of tokenOut converted\n function _postConversionHook(\n address tokenAddressIn,\n address tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n ) internal virtual {}\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init_unchained(\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n _setPriceOracle(priceOracle_);\n _setDestination(destinationAddress_);\n _setMinAmountToConvert(minAmountToConvert_);\n conversionPaused = false;\n }\n\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return Amount of asset, for _privateConversion\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\n\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\n /// destination contract as destination's base asset\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\n function _privateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 amountToConvert\n ) internal {\n address tokenAddressIn = _getDestinationBaseAsset();\n address _destinationAddress = destinationAddress;\n uint256 convertedTokenInBalance;\n if (address(converterNetwork) != address(0)) {\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\n uint256 convertersLength = converterAddresses.length;\n for (uint256 i; i < convertersLength; ) {\n if (converterBalances[i] == 0) break;\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\n converterBalances[i],\n tokenAddressOut,\n tokenAddressIn\n );\n if (amountIn > amountToConvert) {\n amountIn = amountToConvert;\n }\n\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\n break;\n }\n\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\n amountIn,\n 0,\n tokenAddressOut,\n tokenAddressIn,\n _destinationAddress\n );\n\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n amountToConvert -= amountIn;\n convertedTokenInBalance += (balanceAfter - balanceBefore);\n\n if (amountToConvert == 0) break;\n unchecked {\n ++i;\n }\n }\n }\n\n _postPrivateConversionHook(\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance,\n tokenAddressOut,\n amountToConvert\n );\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal virtual {}\n\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\n\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\n /// @param amountIn The amount to convert\n /// @param tokenAddress Address of the token\n /// @return isValid true if amount to convert is greater than minimum amount to convert\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\n priceOracle.updateAssetPrice(tokenAddress);\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\n\n if (amountInInUsd >= minAmountToConvert) {\n isValid = true;\n }\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\n if (amountInMantissa == 0) {\n revert InsufficientInputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\n /// multiplied by conversionWithIncentive which will be >= 1\n amountOutMantissa =\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\n (tokenOutUnderlyingPrice * EXP_SCALE);\n\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n }\n\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\n if (amountOutMantissa == 0) {\n revert InsufficientOutputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\n }\n\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\n if (\n (!(isConverter) &&\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n }\n\n /// @dev To check, is conversion paused\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\n function _checkConversionPaused() internal view {\n if (conversionPaused) {\n revert ConversionTokensPaused();\n }\n }\n\n /// @dev Get base asset address of the destination contract\n /// @return Address of the base asset\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\n}\n" + }, + "contracts/TokenConverter/ConverterNetwork.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { sort } from \"../Utils/ArrayHelpers.sol\";\nimport { IAbstractTokenConverter } from \"./IAbstractTokenConverter.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @title ConverterNetwork\n/// @author Venus\n/// @notice ConverterNetwork keeps track of all the converters and is used to fetch valid converters which provide conversions according to token addresses provided\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract ConverterNetwork is IConverterNetwork, AccessControlledV8, MaxLoopsLimitHelper {\n /// @notice Array holding all the converters\n IAbstractTokenConverter[] public allConverters;\n\n /// @notice Emitted when new converter is added\n event ConverterAdded(address indexed converter);\n\n /// @notice Emitted when converter is removed\n event ConverterRemoved(address indexed converter);\n\n /// @notice Error thrown when converter already exists\n error ConverterAlreadyExists();\n\n /// @notice Error thrown converter does not exist\n error ConverterDoesNotExist();\n\n /// @notice Error thrown when converter address is invalid\n error InvalidTokenConverterAddress();\n\n /// @notice Error thrown when loops limit is invalid\n error InvalidMaxLoopsLimit(uint256 loopsLimit);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @notice ConverterNetwork initializer\n /// @param _accessControlManager The address of ACM contract\n /// @param _loopsLimit Limit for the loops in the contract to avoid DOS\n /// @custom:event ConverterAdded is emitted for each converter added on success\n /// @custom:error InvalidMaxLoopsLimit is thrown when when loops limit is invalid\n function initialize(address _accessControlManager, uint256 _loopsLimit) external initializer {\n ensureNonzeroAddress(_accessControlManager);\n __AccessControlled_init(_accessControlManager);\n\n if (_loopsLimit >= type(uint128).max) revert InvalidMaxLoopsLimit(_loopsLimit);\n _setMaxLoopsLimit(_loopsLimit);\n }\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param limit Limit for the max loops can execute at a time\n * @custom:error InvalidMaxLoopsLimit is thrown when when loops limit is invalid\n * @custom:access Only owner\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n if (limit >= type(uint128).max) revert InvalidMaxLoopsLimit(limit);\n _setMaxLoopsLimit(limit);\n }\n\n /// @notice Adds new converter to the array\n /// @param _tokenConverter Address of the token converter\n /// @custom:event ConverterAdded is emitted on success\n /// @custom:access Only Governance\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external {\n _checkAccessAllowed(\"addTokenConverter(address)\");\n _addTokenConverter(_tokenConverter);\n }\n\n /// @notice Removes converter from the array\n /// @param _tokenConverter Address of the token converter\n /// @custom:error ConverterDoesNotExist is thrown when converter to remove does not exist\n /// @custom:event ConverterRemoved is emitted on success\n /// @custom:access Only Governance\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external {\n _checkAccessAllowed(\"removeTokenConverter(address)\");\n\n // Find the index of the converter in the array\n uint128 indexToRemove = _findConverterIndex(_tokenConverter);\n\n // Ensure that the converter exists in the array\n if (indexToRemove == type(uint128).max) revert ConverterDoesNotExist();\n\n // Swap the element to remove with the last element\n allConverters[indexToRemove] = allConverters[allConverters.length - 1];\n\n // Remove the last element (which is now a duplicate)\n allConverters.pop();\n\n emit ConverterRemoved(address(_tokenConverter));\n }\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// It will return the converters which are open to users for conversion\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance)\n {\n (converters, convertersBalance) = _findTokenConverters(_tokenAddressIn, _tokenAddressOut, false);\n }\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// It will return the converters which are open to converters for conversion.\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance)\n {\n (converters, convertersBalance) = _findTokenConverters(_tokenAddressIn, _tokenAddressOut, true);\n }\n\n /// @notice This function returns the array containing all the converters addresses\n /// @return converters Array containing all the converters addresses\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory converters) {\n converters = allConverters;\n }\n\n /// @notice This function checks if the given address is a converter or not\n /// @param _tokenConverter Address of the token converter\n /// @return isConverter true if given address is converter otherwise false\n function isTokenConverter(address _tokenConverter) external view returns (bool isConverter) {\n uint128 index = _findConverterIndex(IAbstractTokenConverter(_tokenConverter));\n\n if (index != type(uint128).max) {\n isConverter = true;\n }\n }\n\n /// @notice Adds new converter contract to the array\n /// @param _tokenConverter Address of the token converter\n /// @custom:error ConverterAlreadyExists is thrown when new tokenconverter to add already exists\n /// @custom:event ConverterAdded is emitted on success\n function _addTokenConverter(IAbstractTokenConverter _tokenConverter) internal {\n if (\n (address(_tokenConverter) == address(0)) || (address(_tokenConverter.converterNetwork()) != address(this))\n ) {\n revert InvalidTokenConverterAddress();\n }\n\n uint128 index = _findConverterIndex(_tokenConverter);\n if (index != type(uint128).max) revert ConverterAlreadyExists();\n\n allConverters.push(_tokenConverter);\n _ensureMaxLoops(allConverters.length);\n\n emit ConverterAdded(address(_tokenConverter));\n }\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @param forConverters Bool to filter out converters on the basis of the conversionAccess\n /// @return converters Array of converters\n /// @return convertersBalance Array of balances with respect to token out\n function _findTokenConverters(\n address _tokenAddressIn,\n address _tokenAddressOut,\n bool forConverters\n ) internal returns (address[] memory converters, uint256[] memory convertersBalance) {\n uint128 convertersLength = uint128(allConverters.length);\n\n // Create a dynamic array to store the matching converters\n converters = new address[](convertersLength);\n convertersBalance = new uint256[](convertersLength);\n uint128 count;\n\n for (uint128 i; i < convertersLength; ) {\n IAbstractTokenConverter converter = allConverters[i];\n\n unchecked {\n ++i;\n }\n\n if ((address(converter.converterNetwork()) != address(this)) || msg.sender == address(converter)) {\n continue;\n }\n\n (, IAbstractTokenConverter.ConversionAccessibility conversionAccess) = converter.conversionConfigurations(\n _tokenAddressIn,\n _tokenAddressOut\n );\n\n if (conversionAccess == IAbstractTokenConverter.ConversionAccessibility.ALL) {\n converters[count] = address(converter);\n convertersBalance[count] = converter.balanceOf(_tokenAddressOut);\n ++count;\n } else if (\n forConverters &&\n (conversionAccess == IAbstractTokenConverter.ConversionAccessibility.ONLY_FOR_CONVERTERS)\n ) {\n converters[count] = address(converter);\n convertersBalance[count] = converter.balanceOf(_tokenAddressOut);\n ++count;\n } else if (\n !forConverters && (conversionAccess == IAbstractTokenConverter.ConversionAccessibility.ONLY_FOR_USERS)\n ) {\n converters[count] = address(converter);\n convertersBalance[count] = converter.balanceOf(_tokenAddressOut);\n ++count;\n }\n }\n\n // Resize the array to the actual number of matching converters\n assembly {\n mstore(converters, count)\n mstore(convertersBalance, count)\n }\n sort(convertersBalance, converters);\n }\n\n /// @notice Used to get the index of the converter stored in the array\n /// This will return the index if the converter exists in the array otherwise will return type(uint128).max\n /// @param _tokenConverter Address of the token converter\n /// @return index of the converter address in the allConverters array\n function _findConverterIndex(IAbstractTokenConverter _tokenConverter) internal view returns (uint128 index) {\n index = type(uint128).max; // Not found, return a large value\n\n uint128 convertersLength = uint128(allConverters.length);\n for (uint128 i; i < convertersLength; ) {\n if (allConverters[i] == _tokenConverter) {\n index = i;\n }\n unchecked {\n ++i;\n }\n }\n }\n}\n" + }, + "contracts/TokenConverter/IAbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @notice Interface for AbstractTokenConverter\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ninterface IAbstractTokenConverter {\n /// @notice This enum define the all possible ways of conversion can happen\n enum ConversionAccessibility {\n NONE, // Conversion is disable for the pair\n ALL, // Conversion is enable for private conversion and users\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\n ONLY_FOR_USERS // Conversion is enable only for users\n }\n\n /// @notice This struct represents the configuration for a token conversion.\n struct ConversionConfig {\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\n uint256 incentive;\n /// enable or disable conversion for users or converters or both or none\n ConversionAccessibility conversionAccess;\n }\n\n /// @notice Pause conversion of tokens\n function pauseConversion() external;\n\n /// @notice Resume conversion of tokens.\n function resumeConversion() external;\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n function setPriceOracle(ResilientOracle priceOracle_) external;\n\n /// @notice Set the configuration for new or existing convert pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) external;\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Get the configuration for the pair of the tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\n /// @return conversionAccess Accessibility for the pair of tokens\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\n external\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\n\n /// @notice Get the address of the converterNetwork\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) external view returns (uint256 tokenBalance);\n}\n" + }, + "contracts/TokenConverter/RiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\nimport { IPoolRegistry } from \"../Interfaces/IPoolRegistry.sol\";\nimport { IComptroller } from \"../Interfaces/IComptroller.sol\";\nimport { IRiskFund, IRiskFundGetters } from \"../Interfaces/IRiskFund.sol\";\nimport { IVToken } from \"../Interfaces/IVToken.sol\";\n\n/// @title RiskFundConverter\n/// @author Venus\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the core pool comptroller\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n ///@notice Address of the vBNB\n ///@dev This address is used to include the BNB market while in getPools method\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable VBNB;\n\n ///@notice Address of the native wrapped currency\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_WRAPPED;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) internal assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\n\n /// @notice Address of pool registry contract\n address public poolRegistry;\n\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\n\n // Error thrown when comptrollers array length is not equal to assets array length\n error InvalidArguments();\n\n /// @notice thrown when amount entered is greater than balance\n error InsufficientBalance();\n\n /// @notice thrown when asset does not exist in the pool\n error MarketNotExistInPool(address comptroller, address asset);\n\n /// @notice thrown to prevent reentrancy\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\n /// cannot be called recursively within the same transaction.\n error ReentrancyGuardError();\n\n /// @param corePoolComptroller_ Address of the Comptroller pool\n /// @param vBNB_ Address of the vBNB\n /// @param nativeWrapped_ Address of the wrapped native currency\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) {\n ensureNonzeroAddress(corePoolComptroller_);\n ensureNonzeroAddress(vBNB_);\n ensureNonzeroAddress(nativeWrapped_);\n\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\n VBNB = vBNB_;\n NATIVE_WRAPPED = nativeWrapped_;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param poolRegistry_ Address of the pool registry\n /// @param minAmountToConvert_ minimum amount to convert\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address poolRegistry_,\n uint256 minAmountToConvert_,\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) public initializer {\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n ensureNonzeroAddress(poolRegistry_);\n poolRegistry = poolRegistry_;\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Pool registry setter\n /// @param poolRegistry_ Address of the pool registry\n /// @custom:event PoolRegistryUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:access Only Governance\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\n poolRegistry = poolRegistry_;\n }\n\n /// @notice Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:access Restricted by ACM\n function setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) external {\n _checkAccessAllowed(\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\");\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return reserves Asset's reserve in risk fund\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n reserves = poolsAssetsReserves[comptroller][asset];\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Reserves of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n tokenBalance = assetsReserves[tokenAddress];\n }\n\n /// @notice Get the array of all pools addresses\n /// @param tokenAddress Address of the token\n /// @return poolsWithCore Array of the pools addresses in which token is available\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\n\n if (isAssetListedInCore(tokenAddress)) {\n uint256 poolsLength = poolsWithCore.length;\n address[] memory extendedPools = new address[](poolsLength + 1);\n\n for (uint256 i; i < poolsLength; ) {\n extendedPools[i] = poolsWithCore[i];\n unchecked {\n ++i;\n }\n }\n\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\n poolsWithCore = extendedPools;\n }\n }\n\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\n assetsReserves[tokenOutAddress] -= amountOut;\n }\n\n /// @notice Hook to perform after converting tokens\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\n /// @param tokenInAddress Address of the tokenIn\n /// @param tokenOutAddress Address of the tokenOut\n /// @param amountIn Amount of tokenIn transferred\n /// @param amountOut Amount of tokenOut transferred\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\n function _postConversionHook(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) internal override {\n address[] memory pools = getPools(tokenOutAddress);\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\n ensureNonzeroValue(assetReserve);\n\n uint256 poolsLength = pools.length;\n uint256 distributedOutShare;\n uint256 poolAmountInShare;\n uint256 distributedInShare;\n\n for (uint256 i; i < poolsLength; ) {\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\n if (currentPoolsAssetsReserves != 0) {\n if (i < (poolsLength - 1)) {\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\n distributedInShare += poolAmountInShare;\n } else {\n uint256 distributedDiff = amountOut - distributedOutShare;\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\n poolAmountInShare = amountIn - distributedInShare;\n }\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\n }\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Operations to perform before sweeping tokens\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\n if (amount > balance) revert InsufficientBalance();\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\n\n if (balanceDiff < amount) {\n uint256 amountDiff;\n unchecked {\n amountDiff = amount - balanceDiff;\n }\n\n address[] memory pools = getPools(tokenAddress);\n uint256 assetReserve = assetsReserves[tokenAddress];\n uint256 poolsLength = pools.length;\n uint256 distributedShare;\n\n for (uint256 i; i < poolsLength; ) {\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\n if (i < (poolsLength - 1)) {\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\n } else {\n uint256 distributedDiff = amountDiff - distributedShare;\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\n }\n }\n unchecked {\n ++i;\n }\n }\n assetsReserves[tokenAddress] -= amountDiff;\n }\n }\n\n /// @dev Update the poolAssetsReserves upon transferring the tokens\n /// @param pool Address of the pool\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @param assetReserve Asset's reserve for the pool\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\n /// @custom:event AssetsReservesUpdated emits on success\n function updatePoolAssetsReserve(\n address pool,\n address tokenAddress,\n uint256 amount,\n uint256 assetReserve\n ) internal returns (uint256 poolAmountShare) {\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\n }\n\n /// @dev Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\n function _setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) internal {\n uint256 comptrollersLength = comptrollers.length;\n\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < comptrollersLength; ) {\n address[] memory poolAssets = assets[i];\n bool[] memory assetsValues = values[i];\n uint256 poolAssetsLength = poolAssets.length;\n\n if (poolAssetsLength != assetsValues.length) {\n revert InvalidArguments();\n }\n\n for (uint256 j; j < poolAssetsLength; ) {\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\n unchecked {\n ++j;\n }\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\n /// and transferring funds to the protocol share reserve\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return balanceDifference Amount of asset, for _privateConversion\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n function _updateAssetsState(address comptroller, address asset)\n internal\n override\n returns (uint256 balanceDifference)\n {\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 currentBalance = token.balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\n token.safeTransfer(destinationAddress, balanceDifference);\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\n\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\n IRiskFund(destinationAddress).updatePoolState(\n comptroller,\n asset,\n newDestinationBalance - previousDestinationBalance\n );\n balanceDifference = 0;\n }\n }\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n emit AssetTransferredToDestination(\n destinationAddress,\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance\n );\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @dev This function checks for the given asset is listed in core pool or not\n /// @param tokenAddress Address of the asset\n /// @return isAssetListed true if the asset is listed\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\n\n uint256 coreMarketsLength = coreMarkets.length;\n for (uint256 i; i < coreMarketsLength; ) {\n isAssetListed = (VBNB == coreMarkets[i])\n ? (tokenAddress == NATIVE_WRAPPED)\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\n\n if (isAssetListed) {\n break;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev This function checks for the given asset is listed or not\n /// @param comptroller Address of the comptroller\n /// @param asset Address of the asset\n /// @return isListed true if the asset is listed\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\n if (comptroller == CORE_POOL_COMPTROLLER) {\n isListed = isAssetListedInCore(asset);\n } else {\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\n }\n }\n\n /// @dev Get base asset address of the RiskFund\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/TokenConverter/SingleTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\n\n/// @title SingleTokenConverter\n/// @author Venus\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract SingleTokenConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the base asset token\n address public baseAsset;\n\n /// @notice Emitted when base asset is updated\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param baseAsset_ Address of the base asset\n /// @param minAmountToConvert_ Minimum amount to convert\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address baseAsset_,\n uint256 minAmountToConvert_\n ) public initializer {\n _setBaseAsset(baseAsset_);\n\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @notice Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:access Only Governance\n function setBaseAsset(address baseAsset_) external onlyOwner {\n _setBaseAsset(baseAsset_);\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address.\n /// @return balanceLeft Amount of asset, for _privateConversion\n // solhint-disable-next-line\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 balance = token.balanceOf(address(this));\n balanceLeft = balance;\n\n if (asset == baseAsset) {\n balanceLeft = 0;\n token.safeTransfer(destinationAddress, balance);\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\n }\n }\n\n /// @dev Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n /// @custom:event BaseAssetUpdated is emitted on success\n function _setBaseAsset(address baseAsset_) internal {\n ensureNonzeroAddress(baseAsset_);\n emit BaseAssetUpdated(baseAsset, baseAsset_);\n baseAsset = baseAsset_;\n }\n\n /// @dev Get base asset address\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = baseAsset;\n }\n}\n" + }, + "contracts/Utils/ArrayHelpers.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @notice Used to sort addresses array based on their token balances\n/// @param arr Array of token balances of different addresses\n/// @param addrs Array containing these addresses\nfunction sort(uint256[] memory arr, address[] memory addrs) pure {\n if (arr.length > 1) {\n return quickSortDescending(arr, addrs, 0, arr.length - 1);\n }\n}\n\n/// @notice Used to sort addresses array based on their token balances\n/// @param arr Array of token balances of different addresses\n/// @param addrs Array containing these addresses\n/// @param left index of first value\n/// @param right index of last value\nfunction quickSortDescending(\n uint256[] memory arr,\n address[] memory addrs,\n uint256 left,\n uint256 right\n) pure {\n if (left >= right) return;\n uint256 p = arr[(left + right) / 2]; // p = the pivot element\n uint256 i = left;\n uint256 j = right;\n while (i < j) {\n while (arr[i] > p) ++i;\n while (arr[j] < p) --j; // arr[j] < p means p still to the right, so j > 0\n if (arr[i] < arr[j]) {\n (arr[i], arr[j]) = (arr[j], arr[i]);\n (addrs[i], addrs[j]) = (addrs[j], addrs[i]);\n } else {\n ++i;\n }\n }\n\n if (j > left) quickSortDescending(arr, addrs, left, j - 1); // j > left, so j > 0\n quickSortDescending(arr, addrs, j + 1, right);\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} From 9068f8846b583885136bf7ce251261219b12e13f Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Thu, 25 Jan 2024 07:53:13 +0000 Subject: [PATCH 04/53] feat: updating deployment files --- deployments/ethereum.json | 2046 ++++++++++++++++++++++++++- deployments/ethereum_addresses.json | 7 +- 2 files changed, 2051 insertions(+), 2 deletions(-) diff --git a/deployments/ethereum.json b/deployments/ethereum.json index dd24474d..a3504b3b 100644 --- a/deployments/ethereum.json +++ b/deployments/ethereum.json @@ -1,5 +1,2049 @@ { "name": "ethereum", "chainId": "1", - "contracts": {} + "contracts": { + "DefaultProxyAdmin": { + "address": "0x567e4cc5e085d09f66f836fa8279f38b4e5866b9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ] + }, + "ProtocolShareReserve": { + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "percent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "oldPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPoolRegistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" + } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" + } + ], + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolRegistry", + "type": "address" + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ] + }, + "ProtocolShareReserve_Implementation": { + "address": "0xee934792431B4Ebd91591a86c884A8b49Ed494C2", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_corePoolComptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "_wbnb", + "type": "address" + }, + { + "internalType": "address", + "name": "_vbnb", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "percent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "oldPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPoolRegistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" + } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" + } + ], + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolRegistry", + "type": "address" + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "ProtocolShareReserve_Proxy": { + "address": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + } + } } diff --git a/deployments/ethereum_addresses.json b/deployments/ethereum_addresses.json index de562ee9..b460fb72 100644 --- a/deployments/ethereum_addresses.json +++ b/deployments/ethereum_addresses.json @@ -1,5 +1,10 @@ { "name": "ethereum", "chainId": "1", - "addresses": {} + "addresses": { + "DefaultProxyAdmin": "0x567e4cc5e085d09f66f836fa8279f38b4e5866b9", + "ProtocolShareReserve": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E", + "ProtocolShareReserve_Implementation": "0xee934792431B4Ebd91591a86c884A8b49Ed494C2", + "ProtocolShareReserve_Proxy": "0x8c8c8530464f7D95552A11eC31Adbd4dC4AC4d3E" + } } From c487cb5b1f05b26de97b0239f637398d1e0481f4 Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Thu, 25 Jan 2024 09:44:13 +0000 Subject: [PATCH 05/53] chore(release): 1.4.0-dev.3 [skip ci] ## [1.4.0-dev.3](https://github.com/VenusProtocol/protocol-reserve/compare/v1.4.0-dev.2...v1.4.0-dev.3) (2024-01-25) ### Features * deployment files for riskFundV2 ([9aa4058](https://github.com/VenusProtocol/protocol-reserve/commit/9aa4058f4e369c86d8b2aa232ab97d4c2e67297b)) * updating deployment files ([6d6ef46](https://github.com/VenusProtocol/protocol-reserve/commit/6d6ef46924918558534c5c09aded1184cbda6bae)) --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76248784..78d6f4e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [1.4.0-dev.3](https://github.com/VenusProtocol/protocol-reserve/compare/v1.4.0-dev.2...v1.4.0-dev.3) (2024-01-25) + + +### Features + +* deployment files for riskFundV2 ([9aa4058](https://github.com/VenusProtocol/protocol-reserve/commit/9aa4058f4e369c86d8b2aa232ab97d4c2e67297b)) +* updating deployment files ([6d6ef46](https://github.com/VenusProtocol/protocol-reserve/commit/6d6ef46924918558534c5c09aded1184cbda6bae)) + ## [1.4.0-dev.2](https://github.com/VenusProtocol/protocol-reserve/compare/v1.4.0-dev.1...v1.4.0-dev.2) (2024-01-24) diff --git a/package.json b/package.json index 32b50133..e337f5b5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@venusprotocol/protocol-reserve", "description": "Venus Protocol contracts to manage the income generated by the protocol", - "version": "1.4.0-dev.2", + "version": "1.4.0-dev.3", "author": "Venus", "engines": { "node": ">=18.0.0" From 938f3c6e5fd80f810f169d16b370441ea7d2c0d0 Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Fri, 26 Jan 2024 11:08:44 +0000 Subject: [PATCH 06/53] chore(release): 1.5.0-dev.1 [skip ci] ## [1.5.0-dev.1](https://github.com/VenusProtocol/protocol-reserve/compare/v1.4.0...v1.5.0-dev.1) (2024-01-26) ### Features * deployment files for riskFundV2 ([9aa4058](https://github.com/VenusProtocol/protocol-reserve/commit/9aa4058f4e369c86d8b2aa232ab97d4c2e67297b)) * updating deployment files ([6d6ef46](https://github.com/VenusProtocol/protocol-reserve/commit/6d6ef46924918558534c5c09aded1184cbda6bae)) --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8582879f..b79121ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [1.5.0-dev.1](https://github.com/VenusProtocol/protocol-reserve/compare/v1.4.0...v1.5.0-dev.1) (2024-01-26) + + +### Features + +* deployment files for riskFundV2 ([9aa4058](https://github.com/VenusProtocol/protocol-reserve/commit/9aa4058f4e369c86d8b2aa232ab97d4c2e67297b)) +* updating deployment files ([6d6ef46](https://github.com/VenusProtocol/protocol-reserve/commit/6d6ef46924918558534c5c09aded1184cbda6bae)) + ## [1.4.0](https://github.com/VenusProtocol/protocol-reserve/compare/v1.3.0...v1.4.0) (2024-01-24) diff --git a/package.json b/package.json index 9c8b15c6..a1ff1a1e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@venusprotocol/protocol-reserve", "description": "Venus Protocol contracts to manage the income generated by the protocol", - "version": "1.4.0", + "version": "1.5.0-dev.1", "author": "Venus", "engines": { "node": ">=18.0.0" From d5fb61226ff7a4f20f5442b36b1a5aadf8a8d29d Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 8 Feb 2024 20:32:28 +0530 Subject: [PATCH 07/53] refactor: remove round-up in the conversion rates of token converters --- contracts/TokenConverter/AbstractTokenConverter.sol | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/contracts/TokenConverter/AbstractTokenConverter.sol b/contracts/TokenConverter/AbstractTokenConverter.sol index 59201a55..a212a183 100644 --- a/contracts/TokenConverter/AbstractTokenConverter.sol +++ b/contracts/TokenConverter/AbstractTokenConverter.sol @@ -574,9 +574,7 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// If contract has less liquidity for tokenAddressOut than amountOutMantissa if (maxTokenOutReserve < amountOutMantissa) { - amountConvertedMantissa = - ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) / - tokenInToOutConversion; //round-up + amountConvertedMantissa = (maxTokenOutReserve * EXP_SCALE) / tokenInToOutConversion; amountOutMantissa = maxTokenOutReserve; } } @@ -1135,7 +1133,7 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0) - amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up + amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion; } /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag From 21b84734be330ff6e33fa2959d43c7c9623c3265 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 8 Feb 2024 20:33:38 +0530 Subject: [PATCH 08/53] test: fork tests for single token converter --- contracts/Test/imports.sol | 1 + tests/fork/SingleTokenConverter.ts | 139 +++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 tests/fork/SingleTokenConverter.ts diff --git a/contracts/Test/imports.sol b/contracts/Test/imports.sol index d2e8899c..4ecc8d6e 100644 --- a/contracts/Test/imports.sol +++ b/contracts/Test/imports.sol @@ -9,3 +9,4 @@ pragma solidity 0.8.13; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { BeaconProxy } from "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts new file mode 100644 index 00000000..0d0263f1 --- /dev/null +++ b/tests/fork/SingleTokenConverter.ts @@ -0,0 +1,139 @@ +import chai from "chai"; +import hre, { network } from "hardhat"; + +const { expect } = chai; + +const initMainnetUser = async (user: string) => { + await impersonateAccount(user); + return ethers.getSigner(user); +}; + +export async function setForkBlock(blockNumber: number) { + await network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: process.env.BSC_ARCHIVE_NODE, + blockNumber: blockNumber, + }, + }, + ], + }); +} + +const forking = (blockNumber: number, fn: () => void) => { + describe(`riskFundConverter #${blockNumber}`, () => { + before(async () => { + await setForkBlock(blockNumber); + }); + fn(); + }); +}; + +async function impersonateAccount(accountAddress) { + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [accountAddress], + }); +} + +const NORMAL_TIMELOCK = "0x939bD8d64c0A9583A7Dcea9933f7b21697ab6396"; +const PROTOCOL_SHARE_RESERVE = "0xCa01D5A9A248a830E9D93231e791B1afFed7c446"; +const SINGLE_TOKEN_CONVERTER_BEACON_PROXY = "0x4c9D57b05B245c40235D720A5f3A592f3DfF11ca"; +const RISK_FUND_CONVERTER_PROXY = "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0"; +const PROXY_ADMIN = "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4"; + +const CORE_POOL = "0xfd36e2c2a6789db23113685031d7f16329158384"; +//Assets listed in core pool and need to release mfunds for them +const USDT = "0x55d398326f99059fF775485246999027B3197955"; +const BTCB = "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c"; +const ETH = "0x2170Ed0880ac9A755fd29B2688956BD959F933F8"; +const DAI = "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3"; +const TUSD = "0x40af3827F39D0EAcBF4A168f8D4ee67c121D11c9"; +const DOT = "0x7083609fCE4d1d8Dc0C979AAb8c869Ea2C873402"; +const CAKE = "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82"; +const LINK = "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD"; +const TRX = "0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3"; +const FDUSD = "0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409"; +const WBNB = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"; + +forking(35936683, () => { + let protocolShareReserve: ethers.Contract; + let singleTokenConverterBeaconProxy: ethers.Contract; + let proxyAdmin = ethers.Contract; + let singleTokenConverterImplementation = ethers.Contract; + let timeLockSigner: ethers.Signer; + + if (process.env.FORK_MAINNET === "true") { + describe("Single token converter", () => { + before(async () => { + const singleTokenConverterFactory = await hre.ethers.getContractFactory("SingleTokenConverter"); + singleTokenConverterImplementation = await singleTokenConverterFactory.deploy(); + + protocolShareReserve = await hre.ethers.getContractAt("ProtocolShareReserve", PROTOCOL_SHARE_RESERVE); + timeLockSigner = await initMainnetUser(NORMAL_TIMELOCK); + }); + + describe("Failing releaseFund when getAmountIn and getAmountOut are rounding up the values", () => { + it("Failed releaseFund for core pool through PROTOCOL_SHARE_RESERVE", async () => { + await expect( + protocolShareReserve.releaseFunds(CORE_POOL, [ + USDT, + BTCB, + ETH, + DAI, + TUSD, + DOT, + CAKE, + LINK, + TRX, + FDUSD, + WBNB, + ]), + ).to.be.revertedWithCustomError(singleTokenConverterImplementation, "InsufficientPoolLiquidity"); + }); + }); + + describe("Success on releaseFund when getAmountIn and getAmountOut are not rounding up the values", () => { + before(async () => { + const riskFundConverterFactory = await ethers.getContractFactory("RiskFundConverter"); + const riskFundConverterImplementation = await riskFundConverterFactory.deploy( + "0xfD36E2c2a6789Db23113685031d7F16329158384", + "0xA07c5b74C9B40447a954e1466938b865b6BBea36", + "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + ); + + singleTokenConverterBeaconProxy = await hre.ethers.getContractAt( + "UpgradeableBeacon", + SINGLE_TOKEN_CONVERTER_BEACON_PROXY, + ); + proxyAdmin = await hre.ethers.getContractAt("ProxyAdmin", PROXY_ADMIN); + + await singleTokenConverterBeaconProxy + .connect(timeLockSigner) + .upgradeTo(singleTokenConverterImplementation.address); + await proxyAdmin + .connect(timeLockSigner) + .upgrade(RISK_FUND_CONVERTER_PROXY, riskFundConverterImplementation.address); + }); + + it("Succes for core pool through PROTOCOL_SHARE_RESERVE", async () => { + await protocolShareReserve.releaseFunds(CORE_POOL, [ + USDT, + BTCB, + ETH, + DAI, + TUSD, + DOT, + CAKE, + LINK, + TRX, + FDUSD, + WBNB, + ]); + }); + }); + }); + } +}); From b3f420deedfa1bad3dd7174a123d480163e6bb92 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Sat, 10 Feb 2024 15:52:53 +0530 Subject: [PATCH 09/53] test: add amount validation test --- tests/fork/SingleTokenConverter.ts | 77 ++++++++++++++++++------------ 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts index 0d0263f1..ae3b1d2d 100644 --- a/tests/fork/SingleTokenConverter.ts +++ b/tests/fork/SingleTokenConverter.ts @@ -1,4 +1,6 @@ import chai from "chai"; +import { Contract, Signer } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; import hre, { network } from "hardhat"; const { expect } = chai; @@ -44,6 +46,9 @@ const SINGLE_TOKEN_CONVERTER_BEACON_PROXY = "0x4c9D57b05B245c40235D720A5f3A592f3 const RISK_FUND_CONVERTER_PROXY = "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0"; const PROXY_ADMIN = "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4"; +const USDTPrimeConverter = "0xD9f101AA67F3D72662609a2703387242452078C3"; +const BTCBPrimeConverter = "0xE8CeAa79f082768f99266dFd208d665d2Dd18f53"; + const CORE_POOL = "0xfd36e2c2a6789db23113685031d7f16329158384"; //Assets listed in core pool and need to release mfunds for them const USDT = "0x55d398326f99059fF775485246999027B3197955"; @@ -58,12 +63,18 @@ const TRX = "0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3"; const FDUSD = "0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409"; const WBNB = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"; +async function getToken(tokenAddress) { + const token = await hre.ethers.getContractAt("MockToken", tokenAddress); + return token; +} + + forking(35936683, () => { - let protocolShareReserve: ethers.Contract; - let singleTokenConverterBeaconProxy: ethers.Contract; - let proxyAdmin = ethers.Contract; - let singleTokenConverterImplementation = ethers.Contract; - let timeLockSigner: ethers.Signer; + let protocolShareReserve: Contract; + let singleTokenConverterBeaconProxy: Contract; + let proxyAdmin = Contract; + let singleTokenConverterImplementation = Contract; + let timeLockSigner: Signer; if (process.env.FORK_MAINNET === "true") { describe("Single token converter", () => { @@ -78,19 +89,7 @@ forking(35936683, () => { describe("Failing releaseFund when getAmountIn and getAmountOut are rounding up the values", () => { it("Failed releaseFund for core pool through PROTOCOL_SHARE_RESERVE", async () => { await expect( - protocolShareReserve.releaseFunds(CORE_POOL, [ - USDT, - BTCB, - ETH, - DAI, - TUSD, - DOT, - CAKE, - LINK, - TRX, - FDUSD, - WBNB, - ]), + protocolShareReserve.releaseFunds(CORE_POOL, [BTCB]), ).to.be.revertedWithCustomError(singleTokenConverterImplementation, "InsufficientPoolLiquidity"); }); }); @@ -120,20 +119,38 @@ forking(35936683, () => { it("Succes for core pool through PROTOCOL_SHARE_RESERVE", async () => { await protocolShareReserve.releaseFunds(CORE_POOL, [ - USDT, - BTCB, - ETH, - DAI, - TUSD, - DOT, - CAKE, - LINK, - TRX, - FDUSD, - WBNB, + BTCB ]); }); + + it("Validates if released funds are released as expected", async () => { + + const usdt = await getToken(USDT); + + const btcbPrimeConverterBalanceBefore = await usdt.balanceOf(BTCBPrimeConverter); + + await protocolShareReserve.releaseFunds(CORE_POOL, [BTCB]); + + const btcbPrimeConverterBalanceAfter = await usdt.balanceOf(BTCBPrimeConverter); + + // Since we have released the funds the current balance of the converter should be greater than or equal to balance before + expect(btcbPrimeConverterBalanceBefore).to.be.greaterThanOrEqual(btcbPrimeConverterBalanceAfter); + //-------- OLD SCENARIO --------// + // amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up + // amountInMantissa = ((2791059920256193728245 * 1e18) + 44097363325886872486444 - 1) / 44097363325886872486444; + // amountInMantissa = 63293124798183403; + // This turned out assets released from reserves to be equal 2791059920256193753040 + //------------------------------// + //-------- CURRENT SCENARIO --------// + // amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion; + // amountInMantissa = (2791059920256193728245 * 1e18) / 44097363325886872486444; + // amountInMantissa = 63293124798183402; + // This turned out assets released from reserves to be equal 2791059920256193708943 which is less by 44097 hence a minute amount of assets won't be converted. + // Leaving behind a small amount of usdt "19302" with the BTCBPrimeConverter + //----------------------------------// + expect(btcbPrimeConverterBalanceAfter).to.be.greaterThanOrEqual(0); + }); }); }); } -}); +}); \ No newline at end of file From 5486b9909b5d1a2257b8ac7287509e4cd697cd2b Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Mon, 12 Feb 2024 18:29:06 +0530 Subject: [PATCH 10/53] fix: round-up condition suggested by certik --- .../TokenConverter/AbstractTokenConverter.sol | 20 +++++++++++++++---- yarn.lock | 20 ++++++++++++++++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/contracts/TokenConverter/AbstractTokenConverter.sol b/contracts/TokenConverter/AbstractTokenConverter.sol index a212a183..c3eb9db6 100644 --- a/contracts/TokenConverter/AbstractTokenConverter.sol +++ b/contracts/TokenConverter/AbstractTokenConverter.sol @@ -545,6 +545,7 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. /// This function does not account for potential token transfer fees(in case of deflationary tokens) + /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut /// @dev This function retrieves values without altering token prices /// @param amountInMantissa Amount of tokenAddressIn /// @param tokenAddressIn Address of the token to convert @@ -574,7 +575,9 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// If contract has less liquidity for tokenAddressOut than amountOutMantissa if (maxTokenOutReserve < amountOutMantissa) { - amountConvertedMantissa = (maxTokenOutReserve * EXP_SCALE) / tokenInToOutConversion; + amountConvertedMantissa = + ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) / + tokenInToOutConversion; //round-up amountOutMantissa = maxTokenOutReserve; } } @@ -806,6 +809,7 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function + /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert /// @param amountInMaxMantissa Max amount of tokenAddressIn /// @param amountOutMantissa Amount of tokenAddressOut required as output /// @param tokenAddressIn Address of the token to convert @@ -1124,7 +1128,10 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut); uint256 incentive = configuration.incentive; - if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) { + + bool isPrivateConversion = address(converterNetwork) != address(0) && + converterNetwork.isTokenConverter(msg.sender); + if (isPrivateConversion) { incentive = 0; } @@ -1132,8 +1139,13 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo uint256 conversionWithIncentive = MANTISSA_ONE + incentive; tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; - /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0) - amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion; + if (isPrivateConversion) { + /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0) + amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion; + } else { + /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0) + amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up + } } /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag diff --git a/yarn.lock b/yarn.lock index 7849875d..7e040e47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2974,7 +2974,25 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/protocol-reserve@^1.1.0, @venusprotocol/protocol-reserve@^1.2.0, @venusprotocol/protocol-reserve@workspace:.": +"@venusprotocol/protocol-reserve@npm:^1.1.0, @venusprotocol/protocol-reserve@npm:^1.2.0": + version: 1.4.0 + resolution: "@venusprotocol/protocol-reserve@npm:1.4.0" + dependencies: + "@nomiclabs/hardhat-ethers": ^2.2.3 + "@openzeppelin/contracts": ^4.8.3 + "@openzeppelin/contracts-upgradeable": ^4.8.3 + "@openzeppelin/hardhat-upgrades": ^1.21.0 + "@solidity-parser/parser": ^0.13.2 + "@venusprotocol/isolated-pools": ^2.3.0 + "@venusprotocol/solidity-utilities": ^1.3.0 + ethers: ^5.7.0 + hardhat-deploy: ^0.11.14 + module-alias: ^2.2.2 + checksum: 6b9bc35ac7cdb2d828312c9ebcba1c55e3b63d6d8d237affa7b5baf94b5c2a86e296552c153a5c077f9b6178cc73c7fd20804126509a8a8670c5b50eeae41d2d + languageName: node + linkType: hard + +"@venusprotocol/protocol-reserve@workspace:.": version: 0.0.0-use.local resolution: "@venusprotocol/protocol-reserve@workspace:." dependencies: From 09885c04d73f4d858f23a68962cdcc72e899d260 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Mon, 12 Feb 2024 18:29:41 +0530 Subject: [PATCH 11/53] fix: lint --- tests/fork/SingleTokenConverter.ts | 31 +++++++----------------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts index ae3b1d2d..7e25db9e 100644 --- a/tests/fork/SingleTokenConverter.ts +++ b/tests/fork/SingleTokenConverter.ts @@ -1,6 +1,5 @@ import chai from "chai"; import { Contract, Signer } from "ethers"; -import { parseUnits } from "ethers/lib/utils"; import hre, { network } from "hardhat"; const { expect } = chai; @@ -45,30 +44,16 @@ const PROTOCOL_SHARE_RESERVE = "0xCa01D5A9A248a830E9D93231e791B1afFed7c446"; const SINGLE_TOKEN_CONVERTER_BEACON_PROXY = "0x4c9D57b05B245c40235D720A5f3A592f3DfF11ca"; const RISK_FUND_CONVERTER_PROXY = "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0"; const PROXY_ADMIN = "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4"; - -const USDTPrimeConverter = "0xD9f101AA67F3D72662609a2703387242452078C3"; const BTCBPrimeConverter = "0xE8CeAa79f082768f99266dFd208d665d2Dd18f53"; - const CORE_POOL = "0xfd36e2c2a6789db23113685031d7f16329158384"; //Assets listed in core pool and need to release mfunds for them const USDT = "0x55d398326f99059fF775485246999027B3197955"; const BTCB = "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c"; -const ETH = "0x2170Ed0880ac9A755fd29B2688956BD959F933F8"; -const DAI = "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3"; -const TUSD = "0x40af3827F39D0EAcBF4A168f8D4ee67c121D11c9"; -const DOT = "0x7083609fCE4d1d8Dc0C979AAb8c869Ea2C873402"; -const CAKE = "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82"; -const LINK = "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD"; -const TRX = "0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3"; -const FDUSD = "0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409"; -const WBNB = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"; - async function getToken(tokenAddress) { const token = await hre.ethers.getContractAt("MockToken", tokenAddress); return token; } - forking(35936683, () => { let protocolShareReserve: Contract; let singleTokenConverterBeaconProxy: Contract; @@ -88,9 +73,10 @@ forking(35936683, () => { describe("Failing releaseFund when getAmountIn and getAmountOut are rounding up the values", () => { it("Failed releaseFund for core pool through PROTOCOL_SHARE_RESERVE", async () => { - await expect( - protocolShareReserve.releaseFunds(CORE_POOL, [BTCB]), - ).to.be.revertedWithCustomError(singleTokenConverterImplementation, "InsufficientPoolLiquidity"); + await expect(protocolShareReserve.releaseFunds(CORE_POOL, [BTCB])).to.be.revertedWithCustomError( + singleTokenConverterImplementation, + "InsufficientPoolLiquidity", + ); }); }); @@ -118,13 +104,10 @@ forking(35936683, () => { }); it("Succes for core pool through PROTOCOL_SHARE_RESERVE", async () => { - await protocolShareReserve.releaseFunds(CORE_POOL, [ - BTCB - ]); + await protocolShareReserve.releaseFunds(CORE_POOL, [BTCB]); }); it("Validates if released funds are released as expected", async () => { - const usdt = await getToken(USDT); const btcbPrimeConverterBalanceBefore = await usdt.balanceOf(BTCBPrimeConverter); @@ -135,7 +118,7 @@ forking(35936683, () => { // Since we have released the funds the current balance of the converter should be greater than or equal to balance before expect(btcbPrimeConverterBalanceBefore).to.be.greaterThanOrEqual(btcbPrimeConverterBalanceAfter); - //-------- OLD SCENARIO --------// + //-------- OLD SCENARIO --------// // amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up // amountInMantissa = ((2791059920256193728245 * 1e18) + 44097363325886872486444 - 1) / 44097363325886872486444; // amountInMantissa = 63293124798183403; @@ -153,4 +136,4 @@ forking(35936683, () => { }); }); } -}); \ No newline at end of file +}); From b45710205d335807d27146672c5c6be3713daa95 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Mon, 12 Feb 2024 20:50:10 +0530 Subject: [PATCH 12/53] tests: add getAmountIn test --- tests/fork/SingleTokenConverter.ts | 38 +++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts index 7e25db9e..3b5ff7ab 100644 --- a/tests/fork/SingleTokenConverter.ts +++ b/tests/fork/SingleTokenConverter.ts @@ -1,5 +1,6 @@ import chai from "chai"; import { Contract, Signer } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; import hre, { network } from "hardhat"; const { expect } = chai; @@ -44,11 +45,15 @@ const PROTOCOL_SHARE_RESERVE = "0xCa01D5A9A248a830E9D93231e791B1afFed7c446"; const SINGLE_TOKEN_CONVERTER_BEACON_PROXY = "0x4c9D57b05B245c40235D720A5f3A592f3DfF11ca"; const RISK_FUND_CONVERTER_PROXY = "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0"; const PROXY_ADMIN = "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4"; -const BTCBPrimeConverter = "0xE8CeAa79f082768f99266dFd208d665d2Dd18f53"; +const BTCB_PRIME_CONVERTER = "0xE8CeAa79f082768f99266dFd208d665d2Dd18f53"; const CORE_POOL = "0xfd36e2c2a6789db23113685031d7f16329158384"; + //Assets listed in core pool and need to release mfunds for them const USDT = "0x55d398326f99059fF775485246999027B3197955"; const BTCB = "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c"; + +const USDT_HOLDER = "0xf89d7b9c864f589bbF53a82105107622B35EaA40"; + async function getToken(tokenAddress) { const token = await hre.ethers.getContractAt("MockToken", tokenAddress); return token; @@ -110,11 +115,11 @@ forking(35936683, () => { it("Validates if released funds are released as expected", async () => { const usdt = await getToken(USDT); - const btcbPrimeConverterBalanceBefore = await usdt.balanceOf(BTCBPrimeConverter); + const btcbPrimeConverterBalanceBefore = await usdt.balanceOf(BTCB_PRIME_CONVERTER); await protocolShareReserve.releaseFunds(CORE_POOL, [BTCB]); - const btcbPrimeConverterBalanceAfter = await usdt.balanceOf(BTCBPrimeConverter); + const btcbPrimeConverterBalanceAfter = await usdt.balanceOf(BTCB_PRIME_CONVERTER); // Since we have released the funds the current balance of the converter should be greater than or equal to balance before expect(btcbPrimeConverterBalanceBefore).to.be.greaterThanOrEqual(btcbPrimeConverterBalanceAfter); @@ -133,6 +138,33 @@ forking(35936683, () => { //----------------------------------// expect(btcbPrimeConverterBalanceAfter).to.be.greaterThanOrEqual(0); }); + + describe("getAmountIn", () => { + let btcbPrimeConverter: Contract; + let riskFundSigner: Signer; + + beforeEach(async () => { + await protocolShareReserve.releaseFunds(CORE_POOL, [BTCB]); + + btcbPrimeConverter = await hre.ethers.getContractAt("SingleTokenConverter", BTCB_PRIME_CONVERTER); + riskFundSigner = await initMainnetUser(RISK_FUND_CONVERTER_PROXY); + }); + + it("return values should differ for same amountOut given as input during private and user conversion", async () => { + const [, amountInMantissaForUser] = await btcbPrimeConverter.callStatic.getUpdatedAmountIn( + parseUnits("100", 18), + BTCB, + USDT, + ); + const [, amountInMantissaForPrivate] = await btcbPrimeConverter + .connect(riskFundSigner) + .callStatic.getUpdatedAmountIn(parseUnits("100", 18), BTCB, USDT); + + // The amountIn as output by function called when conversion is done by normal user + // should be 1 greater than the amountIn as output received when called as private conversion + expect(amountInMantissaForPrivate).to.equal(amountInMantissaForUser - 1); + }); + }); }); }); } From 684155a8f026fd18555262ca9318fa8038209533 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Tue, 13 Feb 2024 12:37:55 +0530 Subject: [PATCH 13/53] refactor: add round-up comment in netspec --- contracts/TokenConverter/AbstractTokenConverter.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/TokenConverter/AbstractTokenConverter.sol b/contracts/TokenConverter/AbstractTokenConverter.sol index c3eb9db6..14fae87c 100644 --- a/contracts/TokenConverter/AbstractTokenConverter.sol +++ b/contracts/TokenConverter/AbstractTokenConverter.sol @@ -1102,6 +1102,8 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut /// @dev This function retrieves values without altering token prices. + /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa + /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive /// @param tokenAddressIn Address of the token to convert /// @param tokenAddressOut Address of the token to get after conversion @@ -1139,11 +1141,10 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo uint256 conversionWithIncentive = MANTISSA_ONE + incentive; tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; + /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0) if (isPrivateConversion) { - /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0) amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion; } else { - /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0) amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up } } From 9590f0a51d61b9a33d59e7350667662950922fed Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Tue, 13 Feb 2024 14:58:18 +0530 Subject: [PATCH 14/53] feat: update converter implementation deployment files --- .../RiskFundConverter_Implementation.json | 72 +++++----- .../bsctestnet/SingleTokenConverterImp.json | 69 +++++----- .../e9f683aad829bf9574e4eef6b067ab3e.json | 123 ++++++++++++++++++ 3 files changed, 194 insertions(+), 70 deletions(-) create mode 100644 deployments/bsctestnet/solcInputs/e9f683aad829bf9574e4eef6b067ab3e.json diff --git a/deployments/bsctestnet/RiskFundConverter_Implementation.json b/deployments/bsctestnet/RiskFundConverter_Implementation.json index 29b51b77..1772c07d 100644 --- a/deployments/bsctestnet/RiskFundConverter_Implementation.json +++ b/deployments/bsctestnet/RiskFundConverter_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0xbF732B12f87963dF5d7c729E84E5CF3698F8d349", + "address": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", "abi": [ { "inputs": [ @@ -1622,30 +1622,30 @@ "type": "function" } ], - "transactionHash": "0xfad767e8ed7dd26d0bb429a9e293ab1e7c43febfe0abc5667bf44d0785dc3f7d", + "transactionHash": "0x51b90ec28ac939185ebdc2d03af1ddf63add4ec352c4473b396456b0fd7825e7", "receipt": { "to": null, - "from": "0x02EB950C215D12d723b44a18CfF098C6E166C531", - "contractAddress": "0xbF732B12f87963dF5d7c729E84E5CF3698F8d349", - "transactionIndex": 0, - "gasUsed": "4940305", - "logsBloom": "0x00000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000", - "blockHash": "0xdc9ea9055f49f85ad8534f5adfa2a2b57c4a66c911b6d3f13de42ff4dcb34725", - "transactionHash": "0xfad767e8ed7dd26d0bb429a9e293ab1e7c43febfe0abc5667bf44d0785dc3f7d", + "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", + "contractAddress": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", + "transactionIndex": 1, + "gasUsed": "4951352", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe7eb97c3ce0803a746d0c0dc4b0c3653edc508b73f765af46e4d58a18e4f2d54", + "transactionHash": "0x51b90ec28ac939185ebdc2d03af1ddf63add4ec352c4473b396456b0fd7825e7", "logs": [ { - "transactionIndex": 0, - "blockNumber": 36750496, - "transactionHash": "0xfad767e8ed7dd26d0bb429a9e293ab1e7c43febfe0abc5667bf44d0785dc3f7d", - "address": "0xbF732B12f87963dF5d7c729E84E5CF3698F8d349", + "transactionIndex": 1, + "blockNumber": 37698154, + "transactionHash": "0x51b90ec28ac939185ebdc2d03af1ddf63add4ec352c4473b396456b0fd7825e7", + "address": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", "logIndex": 0, - "blockHash": "0xdc9ea9055f49f85ad8534f5adfa2a2b57c4a66c911b6d3f13de42ff4dcb34725" + "blockHash": "0xe7eb97c3ce0803a746d0c0dc4b0c3653edc508b73f765af46e4d58a18e4f2d54" } ], - "blockNumber": 36750496, - "cumulativeGasUsed": "4940305", + "blockNumber": 37698154, + "cumulativeGasUsed": "4982593", "status": 1, "byzantium": true }, @@ -1654,11 +1654,11 @@ "0x2E7222e51c0f6e98610A1543Aa3836E092CDe62c", "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd" ], - "numDeployments": 1, - "solcInputHash": "d02e743d886d63634298edb2c3d7a019", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vBNB_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidArguments\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"MarketNotExistInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetsReservesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"name\":\"PoolAssetsDirectTransferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPoolRegistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPoolRegistry\",\"type\":\"address\"}],\"name\":\"PoolRegistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_COMPTROLLER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NATIVE_WRAPPED\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VBNB\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolAssetReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"getPools\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"poolsWithCore\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolsAssetsDirectTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"setPoolsAssetsDirectTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"errors\":{\"ReentrancyGuardError()\":[{\"details\":\"This error is used to safeguard against reentrancy attacks, ensuring that a certain operation cannot be called recursively within the same transaction.\"}]},\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Reserves of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"corePoolComptroller_\":\"Address of the Comptroller pool\",\"nativeWrapped_\":\"Address of the wrapped native currency\",\"vBNB_\":\"Address of the vBNB\"}},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getPoolAssetReserve(address,address)\":{\"custom:error\":\"MarketNotExistInPool When asset does not exist in the pool(comptroller)ReentrancyGuardError thrown to prevent reentrancy during the function execution\",\"details\":\"Get the Amount of the asset in the risk fund for the specific pool\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"},\"returns\":{\"reserves\":\"Asset's reserve in risk fund\"}},\"getPools(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"poolsWithCore\":\"Array of the pools addresses in which token is available\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256,address[],address[][],bool[][])\":{\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"minimum amount to convert\",\"poolRegistry_\":\"Address of the pool registry\",\"priceOracle_\":\"Resilient oracle address\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPoolRegistry(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"custom:event\":\"PoolRegistryUpdated emits on success\",\"details\":\"Pool registry setter\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"custom:access\":\"Restricted by ACM\",\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"stateVariables\":{\"CORE_POOL_COMPTROLLER\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"NATIVE_WRAPPED\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"VBNB\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\",\"details\":\"This address is used to include the BNB market while in getPools method\"},\"poolsAssetsDirectTransfer\":{\"details\":\"Comptroller(pool) -> Asset -> bool(should transfer directly on true)\"},\"poolsAssetsReserves\":{\"details\":\"Comptroller(pool) -> Asset -> amount\"}},\"title\":\"RiskFundConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"MarketNotExistInPool(address,address)\":[{\"notice\":\"thrown when asset does not exist in the pool\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"ReentrancyGuardError()\":[{\"notice\":\"thrown to prevent reentrancy\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Emitted after updating of the assets reserves amount -> reserve increased by amount\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDirectTransferUpdated(address,address,bool)\":{\"notice\":\"Emitted after the poolsAssetsDirectTransfer mapping is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_COMPTROLLER()\":{\"notice\":\"Address of the core pool comptroller\"},\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"NATIVE_WRAPPED()\":{\"notice\":\"Address of the native wrapped currency\"},\"VBNB()\":{\"notice\":\"Address of the vBNB\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getPools(address)\":{\"notice\":\"Get the array of all pools addresses\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"poolRegistry()\":{\"notice\":\"Address of pool registry contract\"},\"poolsAssetsDirectTransfer(address,address)\":{\"notice\":\"The mapping contains the assets for each pool which are sent to RiskFund directly\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"notice\":\"Update the poolsAssetsDirectTransfer mapping\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"RiskFundConverter used for token conversions and sends received token to RiskFund\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/RiskFundConverter.sol\":\"RiskFundConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IComptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IComptroller {\\n function isComptroller() external view returns (bool);\\n\\n function markets(address) external view returns (bool);\\n\\n function getAllMarkets() external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x7d85db8d34103352b25f29f591c1e45159222f0d2bbafaa3fcd42f42bf9a523d\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IPoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IPoolRegistry {\\n /// @notice Get VToken in the Pool for an Asset\\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\\n\\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb38a3b61926e55588096e0657b758b178130386143a5658030d659038ec7075c\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IVToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IVToken {\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x0718e50835da441b2dddcf6d52a671c43d386b96dbcc9eb41d68c3647b82c117\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa =\\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\\n tokenInToOutConversion; //round-up\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa =\\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\\n (tokenOutUnderlyingPrice * EXP_SCALE);\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n}\\n\",\"keccak256\":\"0xe10a4505a941511a1e57e162dc5b7d6e4874e40ad421828bc4d6366b51b5608c\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/RiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\nimport { IPoolRegistry } from \\\"../Interfaces/IPoolRegistry.sol\\\";\\nimport { IComptroller } from \\\"../Interfaces/IComptroller.sol\\\";\\nimport { IRiskFund, IRiskFundGetters } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IVToken } from \\\"../Interfaces/IVToken.sol\\\";\\n\\n/// @title RiskFundConverter\\n/// @author Venus\\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the core pool comptroller\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable CORE_POOL_COMPTROLLER;\\n\\n ///@notice Address of the vBNB\\n ///@dev This address is used to include the BNB market while in getPools method\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable VBNB;\\n\\n ///@notice Address of the native wrapped currency\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable NATIVE_WRAPPED;\\n\\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\\n mapping(address => uint256) internal assetsReserves;\\n\\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\\n /// @dev Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\\n\\n /// @notice Address of pool registry contract\\n address public poolRegistry;\\n\\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\\n\\n /// @notice Emitted when pool registry address is updated\\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\\n\\n /// @notice Emitted after updating of the assets reserves\\n /// amount -> reserve increased by amount\\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\\n\\n // Error thrown when comptrollers array length is not equal to assets array length\\n error InvalidArguments();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice thrown when asset does not exist in the pool\\n error MarketNotExistInPool(address comptroller, address asset);\\n\\n /// @notice thrown to prevent reentrancy\\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\\n /// cannot be called recursively within the same transaction.\\n error ReentrancyGuardError();\\n\\n /// @param corePoolComptroller_ Address of the Comptroller pool\\n /// @param vBNB_ Address of the vBNB\\n /// @param nativeWrapped_ Address of the wrapped native currency\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address corePoolComptroller_,\\n address vBNB_,\\n address nativeWrapped_\\n ) {\\n ensureNonzeroAddress(corePoolComptroller_);\\n ensureNonzeroAddress(vBNB_);\\n ensureNonzeroAddress(nativeWrapped_);\\n\\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\\n VBNB = vBNB_;\\n NATIVE_WRAPPED = nativeWrapped_;\\n\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param poolRegistry_ Address of the pool registry\\n /// @param minAmountToConvert_ minimum amount to convert\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address poolRegistry_,\\n uint256 minAmountToConvert_,\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) public initializer {\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n ensureNonzeroAddress(poolRegistry_);\\n poolRegistry = poolRegistry_;\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Pool registry setter\\n /// @param poolRegistry_ Address of the pool registry\\n /// @custom:event PoolRegistryUpdated emits on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:access Only Governance\\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\\n ensureNonzeroAddress(poolRegistry_);\\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\\n poolRegistry = poolRegistry_;\\n }\\n\\n /// @notice Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:access Restricted by ACM\\n function setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) external {\\n _checkAccessAllowed(\\\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\\\");\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return reserves Asset's reserve in risk fund\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n reserves = poolsAssetsReserves[comptroller][asset];\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Reserves of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n tokenBalance = assetsReserves[tokenAddress];\\n }\\n\\n /// @notice Get the array of all pools addresses\\n /// @param tokenAddress Address of the token\\n /// @return poolsWithCore Array of the pools addresses in which token is available\\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\\n\\n if (isAssetListedInCore(tokenAddress)) {\\n uint256 poolsLength = poolsWithCore.length;\\n address[] memory extendedPools = new address[](poolsLength + 1);\\n\\n for (uint256 i; i < poolsLength; ) {\\n extendedPools[i] = poolsWithCore[i];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\\n poolsWithCore = extendedPools;\\n }\\n }\\n\\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\\n assetsReserves[tokenOutAddress] -= amountOut;\\n }\\n\\n /// @notice Hook to perform after converting tokens\\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\\n /// @param tokenInAddress Address of the tokenIn\\n /// @param tokenOutAddress Address of the tokenOut\\n /// @param amountIn Amount of tokenIn transferred\\n /// @param amountOut Amount of tokenOut transferred\\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\\n function _postConversionHook(\\n address tokenInAddress,\\n address tokenOutAddress,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal override {\\n address[] memory pools = getPools(tokenOutAddress);\\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\\n ensureNonzeroValue(assetReserve);\\n\\n uint256 poolsLength = pools.length;\\n uint256 distributedOutShare;\\n uint256 poolAmountInShare;\\n uint256 distributedInShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\\n if (currentPoolsAssetsReserves != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\\n distributedInShare += poolAmountInShare;\\n } else {\\n uint256 distributedDiff = amountOut - distributedOutShare;\\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\\n poolAmountInShare = amountIn - distributedInShare;\\n }\\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n\\n address[] memory pools = getPools(tokenAddress);\\n uint256 assetReserve = assetsReserves[tokenAddress];\\n uint256 poolsLength = pools.length;\\n uint256 distributedShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\\n } else {\\n uint256 distributedDiff = amountDiff - distributedShare;\\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n assetsReserves[tokenAddress] -= amountDiff;\\n }\\n }\\n\\n /// @dev Update the poolAssetsReserves upon transferring the tokens\\n /// @param pool Address of the pool\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @param assetReserve Asset's reserve for the pool\\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\\n /// @custom:event AssetsReservesUpdated emits on success\\n function updatePoolAssetsReserve(\\n address pool,\\n address tokenAddress,\\n uint256 amount,\\n uint256 assetReserve\\n ) internal returns (uint256 poolAmountShare) {\\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\\n }\\n\\n /// @dev Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\\n function _setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) internal {\\n uint256 comptrollersLength = comptrollers.length;\\n\\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 i; i < comptrollersLength; ) {\\n address[] memory poolAssets = assets[i];\\n bool[] memory assetsValues = values[i];\\n uint256 poolAssetsLength = poolAssets.length;\\n\\n if (poolAssetsLength != assetsValues.length) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 j; j < poolAssetsLength; ) {\\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\\n unchecked {\\n ++j;\\n }\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// and transferring funds to the protocol share reserve\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return balanceDifference Amount of asset, for _privateConversion\\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n function _updateAssetsState(address comptroller, address asset)\\n internal\\n override\\n returns (uint256 balanceDifference)\\n {\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 currentBalance = token.balanceOf(address(this));\\n uint256 assetReserve = assetsReserves[asset];\\n if (currentBalance > assetReserve) {\\n unchecked {\\n balanceDifference = currentBalance - assetReserve;\\n }\\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\\n token.safeTransfer(destinationAddress, balanceDifference);\\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\\n\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\\n IRiskFund(destinationAddress).updatePoolState(\\n comptroller,\\n asset,\\n newDestinationBalance - previousDestinationBalance\\n );\\n balanceDifference = 0;\\n }\\n }\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal override {\\n if (convertedTokenInBalance > 0) {\\n emit AssetTransferredToDestination(\\n destinationAddress,\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance\\n );\\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\\n }\\n if (convertedTokenOutBalance > 0) {\\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed in core pool or not\\n /// @param tokenAddress Address of the asset\\n /// @return isAssetListed true if the asset is listed\\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\\n\\n uint256 coreMarketsLength = coreMarkets.length;\\n for (uint256 i; i < coreMarketsLength; ) {\\n isAssetListed = (VBNB == coreMarkets[i])\\n ? (tokenAddress == NATIVE_WRAPPED)\\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\\n\\n if (isAssetListed) {\\n break;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed or not\\n /// @param comptroller Address of the comptroller\\n /// @param asset Address of the asset\\n /// @return isListed true if the asset is listed\\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\\n if (comptroller == CORE_POOL_COMPTROLLER) {\\n isListed = isAssetListedInCore(asset);\\n } else {\\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n }\\n\\n /// @dev Get base asset address of the RiskFund\\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\\n }\\n}\\n\",\"keccak256\":\"0xa9fda55440f25049f1946980b801723cf2111584253a1c11ac1bb7d773cbe39e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b5060405162005a8738038062005a8783398101604081905262000034916200018a565b6200003f8362000081565b6200004a8262000081565b620000558162000081565b6001600160a01b0380841660805282811660a052811660c05262000078620000ac565b505050620001d4565b6001600160a01b038116620000a9576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff1615620001195760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016b576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018557600080fd5b919050565b600080600060608486031215620001a057600080fd5b620001ab846200016d565b9250620001bb602085016200016d565b9150620001cb604085016200016d565b90509250925092565b60805160a05160c05161586062000227600039600081816103e20152612d080152600081816103bb0152612c450152600081816106c501528181610d7a01528181612b8c015261346501526158606000f3fe608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614db1565b6106f0565b005b61037b610376366004614dce565b610704565b60408051928352602083019190915201610315565b61036661039e366004614db1565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e10565b6107d0565b610343610425366004614e6f565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614db1565b61091a565b610366610467366004614db1565b61092b565b61036661047a366004614ef4565b61093c565b61036661048d366004614f8e565b610973565b610366610b4a565b6104ad6104a8366004614db1565b610c30565b604051610315919061507b565b61037b6104c8366004614dce565b610dcc565b6103666104db3660046150c8565b610eca565b61037b6104ee366004614dce565b610f71565b61037b610501366004614dce565b61107a565b610519610514366004614e6f565b611179565b604051908152602001610315565b610519610535366004614db1565b6001600160a01b0316600090815261012d602052604090205490565b61036661123e565b610366610567366004615109565b611252565b610366611299565b610366610582366004614db1565b611324565b6033546001600160a01b0316610301565b61037b6105a6366004614e10565b6113ab565b6103666105b9366004614e6f565b6114a1565b61012f54610301906001600160a01b031681565b6106076105e0366004614e6f565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b60405161031592919061518c565b6097546001600160a01b0316610301565b61037b610634366004614e10565b6114d7565b6103666115cd565b61036661064f3660046151a0565b61167f565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e10565b61171d565b6103666106a8366004615250565b61184c565b6103666106bb366004614db1565b611bf5565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c7e565b61070181611cd8565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615122565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d55565b508092505050935093915050565b6107c7611c7e565b61070181612079565b6000808285856107de61216e565b6107e7836121c3565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610857612203565b6108648a8a8a8a8a61225c565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c7e565b61070181612657565b610933611c7e565b610701816126d4565b61095d6040518060600160405280603c81526020016157ef603c9139612751565b61096b86868686868661281d565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612aee565b610a97896121c3565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad987878787878761281d565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250612751565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153b9565b9050610cc882612b87565b15610dc75780516000610cdc82600161541d565b67ffffffffffffffff811115610cf457610cf46152c1565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615435565b6020026020010151828281518110610d5757610d57615435565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615435565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615122565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d53565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ec05781600181610e9c670de0b6b3a764000085615464565b610ea6919061541d565b610eb091906154a1565b610eba91906154b8565b93508092505b5050935093915050565b610ed2611c7e565b610eda612203565b610ee3836121c3565b610eec826121c3565b610ef581613074565b82610f0081836130ae565b610f146001600160a01b03821684846133b8565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f5991815260200190565b60405180910390a350610f6c600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561104d57600080fd5b505af1158015611061573d6000803e3d6000fd5b50505050611070858585612d53565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110de57600080fd5b505af11580156110f2573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561115657600080fd5b505af115801561116a573d6000803e3d6000fd5b50505050611070858585611d55565b600061118760c95460021490565b156111be576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c88383613461565b611211576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b611246611c7e565b6112506000613551565b565b6112906040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250612751565b61070181613582565b60655433906001600160a01b0316811461131b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613551565b61132c611c7e565b611335816121c3565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113b961216e565b6113c2836121c3565b816001600160a01b0316836001600160a01b031614806113f35750806001600160a01b0316836001600160a01b0316145b1561142a576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611432612203565b61143f8a8a8a8a8a61225c565b9095509350611450888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b6114a9612203565b60006114b583836135cc565b905080156114c8576114c8838383613929565b506114d3600160c955565b5050565b6000808285856114e561216e565b6114ee836121c3565b816001600160a01b0316836001600160a01b0316148061151f5750806001600160a01b0316836001600160a01b0316145b15611556576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61155e612203565b61156b8a8a8a8a8a613dc5565b909550935061157c888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b61160b6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250612751565b61161361216e565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116b9576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156117145761170c878787848181106116da576116da615435565b90506020020160208101906116ef9190614db1565b86868581811061170157611701615435565b90506040020161184c565b6001016116bc565b50505050505050565b60008082858561172b61216e565b611734836121c3565b816001600160a01b0316836001600160a01b031614806117655750806001600160a01b0316836001600160a01b0316145b1561179c576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117a4612203565b6117b18a8a8a8a8a613e57565b90955093508884146117ef576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117fb888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b61186d6040518060600160405280603581526020016157ba60359139612751565b611876836121c3565b61187f826121c3565b6706f05b59d3b20000813511156118d3576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b0316148061190c57506118f6613f14565b6001600160a01b0316836001600160a01b031614155b80611954575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561195157611951615122565b14155b1561198b576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261199d60408301602084016154f3565b60038111156119ae576119ae615122565b1480156119bb5750803515155b156119f2576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002611a0460408301602084016154f3565b6003811115611a1557611a15615122565b1480611a4157506001611a2e60408301602084016154f3565b6003811115611a3f57611a3f615122565b145b8015611a56575060ff546001600160a01b0316155b15611a8d576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611afd91908a01908a016154f3565b604051611b0d9493929190615514565b60405180910390a36000611b2760408401602085016154f3565b6003811115611b3857611b38615122565b03611b95576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bef565b81358155611ba960408301602084016154f3565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611be957611be9615122565b02179055505b50505050565b611bfd611c7e565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c466033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611ce1816121c3565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d92576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611de657611de6615122565b6003811115611df757611df7615122565b9052509050600081602001516003811115611e1457611e14615122565b03611e4b576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190615545565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f609190615545565b835160ff54919250906001600160a01b031615801590612000575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612000919061555e565b15612009575060005b600061201d82670de0b6b3a764000061541d565b90508261202a8286615464565b61203491906154b8565b95508560018161204c670de0b6b3a76400008e615464565b612056919061541d565b61206091906154a1565b61206a91906154b8565b96505050505050935093915050565b6001600160a01b0381166120f55760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611250576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c954036122555760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b6000806122698585613fa0565b61227385886140c0565b9150612280828686610f71565b915050858110156122c7576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b6122d284848361420b565b9550959350505050565b60006122e784610c30565b6001600160a01b038516600090815261012d60205260408120549192509061231090849061541d565b905061231b81613074565b815160008080805b8481101561264357600061012e600089848151811061234457612344615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b031681526020019081526020016000205490508060001461263a576123a56001876154a1565b821015612405576123d18883815181106123c1576123c1615435565b60200260200101518c8b8a614285565b6123db908661541d565b9450866123e8828c615464565b6123f291906154b8565b93506123fe848461541d565b9250612500565b6000612411868b6154a1565b90508061012e60008b868151811061242b5761242b615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461248591906154a1565b925050819055508b6001600160a01b03168984815181106124a8576124a8615435565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce38836040516124ea91815260200190565b60405180910390a36124fc848c6154a1565b9450505b8b6001600160a01b031688838151811061251c5761251c615435565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af558760405161257d91815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125ae576125ae615435565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561262157600080fd5b505af1158015612635573d6000803e3d6000fd5b505050505b50600101612323565b5050505050505050505050565b600160c955565b612660816121c3565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6126dd816121c3565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab9061279d90339086906004016155d8565b602060405180830381865afa1580156127ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127de919061555e565b9050806114d3573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b939291906155fa565b84838114158061282d5750808214155b15612864576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612ae457600086868381811061288357612883615435565b90506020028101906128959190615626565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509394508892508791508590508181106128dd576128dd615435565b90506020028101906128ef9190615626565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508451835193945092831491506129629050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612ad55782818151811061297f5761297f615435565b602002602001015161013060008e8e8981811061299e5761299e615435565b90506020020160208101906129b39190614db1565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008684815181106129e7576129e7615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a3857612a38615435565b60200260200101516001600160a01b03168c8c87818110612a5b57612a5b615435565b9050602002016020810190612a709190614db1565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612aac57612aac615435565b6020026020010151604051612ac5911515815260200190565b60405180910390a3600101612965565b50836001019350505050612867565b5050505050505050565b600054610100900460ff16612b6b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612b748461435e565b612b7c6143ec565b611bef838383614471565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612be8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c1091908101906153b9565b805190915060005b81811015612d4b57828181518110612c3257612c32615435565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d0657846001600160a01b0316838281518110612c8e57612c8e615435565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf7919061568e565b6001600160a01b031614612d3c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d4b57600101612c18565b505050919050565b60008084600003612d90576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612de457612de4615122565b6003811115612df557612df5615122565b9052509050600081602001516003811115612e1257612e12615122565b03612e49576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ead573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed19190615545565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5e9190615545565b835160ff54919250906001600160a01b031615801590612ffe575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffe919061555e565b15613007575060005b600061301b82670de0b6b3a764000061541d565b905061302f670de0b6b3a764000084615464565b8161303a868d615464565b6130449190615464565b61304e91906154b8565b96508261305b8286615464565b61306591906154b8565b95505050505050935093915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561310e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131329190615545565b90508082111561316e576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d602052604081205461319290836154a1565b905082811015611bef5780830360006131aa86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b8281101561337e5761012e60008683815181106131ec576131ec615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133765761324a6001846154a1565b8110156132875761327685828151811061326657613266615435565b60200260200101518b8887614285565b613280908361541d565b9150613376565b600061329383886154a1565b90508061012e60008885815181106132ad576132ad615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461330791906154a1565b925050819055508a6001600160a01b031686838151811061332a5761332a615435565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161336c91815260200190565b60405180910390a3505b6001016131cd565b506001600160a01b038916600090815261012d6020526040812080548792906133a89084906154a1565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f6c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614536565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134ac576134a582612b87565b905061354b565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015613519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353d919061568e565b6001600160a01b0316141590505b92915050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556107018161461e565b61358b81613074565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b60006135d88383613461565b613621576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015613683573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a79190615545565b6001600160a01b038516600090815261012d602052604090205490915080821115613920576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff16156139205760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa158015613765573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137899190615545565b60fe549091506137a6906001600160a01b038681169116876133b8565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561380b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061382f9190615545565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac3537898961389a86866154a1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561390157600080fd5b505af1158015613915573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613933613f14565b60fe5460ff549192506001600160a01b03908116916000911615613db85760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156139c2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139ea91908101906156ab565b8151919350915060005b81811015613db357828181518110613a0e57613a0e615435565b602002602001015160000315613db3576000848281518110613a3257613a32615435565b60200260200101516001600160a01b0316636f1a30a8858481518110613a5a57613a5a615435565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613a9c939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ade9190615766565b91505088811115613aec5750875b613af6818b614688565b613b005750613db3565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b879190615545565b90508a6001600160a01b031663095ea7b3878581518110613baa57613baa615435565b6020026020010151846040518363ffffffff1660e01b8152600401613be49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c27919061555e565b50858381518110613c3a57613c3a615435565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ce89190615766565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d719190615545565b9050613d7d838c6154a1565b9a50613d8982826154a1565b613d93908961541d565b97508a600003613da557505050613db3565b8360010193505050506139f4565b505050505b61096b86848388886147c0565b600080613dd28585613fa0565b6000613ddf87878761107a565b91505087811115613e26576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e3086826140c0565b9250613e3d838787610f71565b9250613e4c905085858461420b565b509550959350505050565b600080613e648585613fa0565b6000613e7187878761107a565b915050613e7e86826140c0565b9250808314613eb9576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613efd576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f0885858961420b565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f9b919061568e565b905090565b60ff546000906001600160a01b03161580159061403d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015614019573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061403d919061555e565b905080158015614089575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff16600381111561408757614087615122565b145b15610f6c576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015614129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061414d9190615545565b60fe5490915061416c906001600160a01b03848116913391168761495e565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa1580156141d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141f59190615545565b905061420182826154a1565b9695505050505050565b6001600160a01b038316600090815261012d60205260409020548181101561425f576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61426984836149af565b8361427e6001600160a01b03821685856133b8565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142bb908590615464565b6142c591906154b8565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143029084906154a1565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161434e91815260200190565b60405180910390a3949350505050565b600054610100900460ff166143db5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6143e36149e1565b61070181614a66565b600054610100900460ff166144695760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614ae3565b600054610100900460ff166144ee5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6144f7836126d4565b61450082611cd8565b61450981613582565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b600061458b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b609092919063ffffffff16565b90508051600014806145ac5750808060200190518101906145ac919061555e565b610f6c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b1580156146e957600080fd5b505af11580156146fd573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa158015614771573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147959190615545565b61479f9190615464565b6147a991906154b8565b905060fb5481106147b957600191505b5092915050565b82156148975760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b15801561487e57600080fd5b505af1158015614892573d6000803e3d6000fd5b505050505b801561427e576001600160a01b038216600090815261012d6020526040812080548392906148c690849061541d565b90915550506001600160a01b03808616600090815261012e602090815260408083209386168352929052908120805483929061490390849061541d565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161494f91815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bef9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016133fd565b6001600160a01b038216600090815261012d6020526040812080548392906149d89084906154a1565b90915550505050565b600054610100900460ff16614a5e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614b79565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126505760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614b6f8484600085614bff565b90505b9392505050565b600054610100900460ff16614bf65760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61125033613551565b606082471015614c775760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614c93919061578a565b60006040518083038185875af1925050503d8060008114614cd0576040519150601f19603f3d011682016040523d82523d6000602084013e614cd5565b606091505b5091509150614ce687838387614cf3565b925050505b949350505050565b60608315614d62578251600003614d5b576001600160a01b0385163b614d5b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614ceb565b614ceb8383815115614d775781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157a6565b6001600160a01b038116811461070157600080fd5b8035610dc781614d91565b600060208284031215614dc357600080fd5b8135614b7281614d91565b600080600060608486031215614de357600080fd5b833592506020840135614df581614d91565b91506040840135614e0581614d91565b809150509250925092565b600080600080600060a08688031215614e2857600080fd5b85359450602086013593506040860135614e4181614d91565b92506060860135614e5181614d91565b91506080860135614e6181614d91565b809150509295509295909350565b60008060408385031215614e8257600080fd5b8235614e8d81614d91565b91506020830135614e9d81614d91565b809150509250929050565b60008083601f840112614eba57600080fd5b50813567ffffffffffffffff811115614ed257600080fd5b6020830191508360208260051b8501011115614eed57600080fd5b9250929050565b60008060008060008060608789031215614f0d57600080fd5b863567ffffffffffffffff80821115614f2557600080fd5b614f318a838b01614ea8565b90985096506020890135915080821115614f4a57600080fd5b614f568a838b01614ea8565b90965094506040890135915080821115614f6f57600080fd5b50614f7c89828a01614ea8565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fb057600080fd5b614fb98c614da6565b9a50614fc760208d01614da6565b9950614fd560408d01614da6565b9850614fe360608d01614da6565b975060808c0135965067ffffffffffffffff8060a08e0135111561500657600080fd5b6150168e60a08f01358f01614ea8565b909750955060c08d013581101561502c57600080fd5b61503c8e60c08f01358f01614ea8565b909550935060e08d013581101561505257600080fd5b506150638d60e08e01358e01614ea8565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150bc5783516001600160a01b031683529284019291840191600101615097565b50909695505050505050565b6000806000606084860312156150dd57600080fd5b83356150e881614d91565b925060208401356150f881614d91565b929592945050506040919091013590565b60006020828403121561511b57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110615188577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614b726020830184615151565b6000806000806000606086880312156151b857600080fd5b85356151c381614d91565b9450602086013567ffffffffffffffff808211156151e057600080fd5b6151ec89838a01614ea8565b9096509450604088013591508082111561520557600080fd5b818801915088601f83011261521957600080fd5b81358181111561522857600080fd5b8960208260061b850101111561523d57600080fd5b9699959850939650602001949392505050565b6000806000838503608081121561526657600080fd5b843561527181614d91565b9350602085013561528181614d91565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152b357600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715615319576153196152c1565b604052919050565b600067ffffffffffffffff82111561533b5761533b6152c1565b5060051b60200190565b600082601f83011261535657600080fd5b8151602061536b61536683615321565b6152f0565b82815260059290921b8401810191818101908684111561538a57600080fd5b8286015b848110156153ae5780516153a181614d91565b835291830191830161538e565b509695505050505050565b6000602082840312156153cb57600080fd5b815167ffffffffffffffff8111156153e257600080fd5b614ceb84828501615345565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615430576154306153ee565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561549c5761549c6153ee565b500290565b6000828210156154b3576154b36153ee565b500390565b6000826154ee577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561550557600080fd5b813560048110614b7257600080fd5b848152602081018490526080810161552f6040830185615151565b61553c6060830184615151565b95945050505050565b60006020828403121561555757600080fd5b5051919050565b60006020828403121561557057600080fd5b81518015158114614b7257600080fd5b60005b8381101561559b578181015183820152602001615583565b83811115611bef5750506000910152565b600081518084526155c4816020860160208601615580565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614b6f60408301846155ac565b60006001600160a01b0380861683528085166020840152506060604083015261553c60608301846155ac565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261565b57600080fd5b83018035915067ffffffffffffffff82111561567657600080fd5b6020019150600581901b3603821315614eed57600080fd5b6000602082840312156156a057600080fd5b8151614b7281614d91565b600080604083850312156156be57600080fd5b825167ffffffffffffffff808211156156d657600080fd5b6156e286838701615345565b93506020915081850151818111156156f957600080fd5b85019050601f8101861361570c57600080fd5b805161571a61536682615321565b81815260059190911b8201830190838101908883111561573957600080fd5b928401925b828410156157575783518252928401929084019061573e565b80955050505050509250929050565b6000806040838503121561577957600080fd5b505080516020909101519092909150565b6000825161579c818460208701615580565b9190910192915050565b602081526000614b7260208301846155ac56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a26469706673582212200c4c1be8186609d8812933be8513b877d4d7456c543e250549bac4e27cafee1364736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614db1565b6106f0565b005b61037b610376366004614dce565b610704565b60408051928352602083019190915201610315565b61036661039e366004614db1565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e10565b6107d0565b610343610425366004614e6f565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614db1565b61091a565b610366610467366004614db1565b61092b565b61036661047a366004614ef4565b61093c565b61036661048d366004614f8e565b610973565b610366610b4a565b6104ad6104a8366004614db1565b610c30565b604051610315919061507b565b61037b6104c8366004614dce565b610dcc565b6103666104db3660046150c8565b610eca565b61037b6104ee366004614dce565b610f71565b61037b610501366004614dce565b61107a565b610519610514366004614e6f565b611179565b604051908152602001610315565b610519610535366004614db1565b6001600160a01b0316600090815261012d602052604090205490565b61036661123e565b610366610567366004615109565b611252565b610366611299565b610366610582366004614db1565b611324565b6033546001600160a01b0316610301565b61037b6105a6366004614e10565b6113ab565b6103666105b9366004614e6f565b6114a1565b61012f54610301906001600160a01b031681565b6106076105e0366004614e6f565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b60405161031592919061518c565b6097546001600160a01b0316610301565b61037b610634366004614e10565b6114d7565b6103666115cd565b61036661064f3660046151a0565b61167f565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e10565b61171d565b6103666106a8366004615250565b61184c565b6103666106bb366004614db1565b611bf5565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c7e565b61070181611cd8565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615122565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d55565b508092505050935093915050565b6107c7611c7e565b61070181612079565b6000808285856107de61216e565b6107e7836121c3565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610857612203565b6108648a8a8a8a8a61225c565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c7e565b61070181612657565b610933611c7e565b610701816126d4565b61095d6040518060600160405280603c81526020016157ef603c9139612751565b61096b86868686868661281d565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612aee565b610a97896121c3565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad987878787878761281d565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250612751565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153b9565b9050610cc882612b87565b15610dc75780516000610cdc82600161541d565b67ffffffffffffffff811115610cf457610cf46152c1565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615435565b6020026020010151828281518110610d5757610d57615435565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615435565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615122565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d53565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ec05781600181610e9c670de0b6b3a764000085615464565b610ea6919061541d565b610eb091906154a1565b610eba91906154b8565b93508092505b5050935093915050565b610ed2611c7e565b610eda612203565b610ee3836121c3565b610eec826121c3565b610ef581613074565b82610f0081836130ae565b610f146001600160a01b03821684846133b8565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f5991815260200190565b60405180910390a350610f6c600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561104d57600080fd5b505af1158015611061573d6000803e3d6000fd5b50505050611070858585612d53565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110de57600080fd5b505af11580156110f2573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561115657600080fd5b505af115801561116a573d6000803e3d6000fd5b50505050611070858585611d55565b600061118760c95460021490565b156111be576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c88383613461565b611211576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b611246611c7e565b6112506000613551565b565b6112906040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250612751565b61070181613582565b60655433906001600160a01b0316811461131b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613551565b61132c611c7e565b611335816121c3565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113b961216e565b6113c2836121c3565b816001600160a01b0316836001600160a01b031614806113f35750806001600160a01b0316836001600160a01b0316145b1561142a576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611432612203565b61143f8a8a8a8a8a61225c565b9095509350611450888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b6114a9612203565b60006114b583836135cc565b905080156114c8576114c8838383613929565b506114d3600160c955565b5050565b6000808285856114e561216e565b6114ee836121c3565b816001600160a01b0316836001600160a01b0316148061151f5750806001600160a01b0316836001600160a01b0316145b15611556576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61155e612203565b61156b8a8a8a8a8a613dc5565b909550935061157c888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b61160b6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250612751565b61161361216e565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116b9576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156117145761170c878787848181106116da576116da615435565b90506020020160208101906116ef9190614db1565b86868581811061170157611701615435565b90506040020161184c565b6001016116bc565b50505050505050565b60008082858561172b61216e565b611734836121c3565b816001600160a01b0316836001600160a01b031614806117655750806001600160a01b0316836001600160a01b0316145b1561179c576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117a4612203565b6117b18a8a8a8a8a613e57565b90955093508884146117ef576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117fb888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b61186d6040518060600160405280603581526020016157ba60359139612751565b611876836121c3565b61187f826121c3565b6706f05b59d3b20000813511156118d3576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b0316148061190c57506118f6613f14565b6001600160a01b0316836001600160a01b031614155b80611954575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561195157611951615122565b14155b1561198b576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261199d60408301602084016154f3565b60038111156119ae576119ae615122565b1480156119bb5750803515155b156119f2576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002611a0460408301602084016154f3565b6003811115611a1557611a15615122565b1480611a4157506001611a2e60408301602084016154f3565b6003811115611a3f57611a3f615122565b145b8015611a56575060ff546001600160a01b0316155b15611a8d576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611afd91908a01908a016154f3565b604051611b0d9493929190615514565b60405180910390a36000611b2760408401602085016154f3565b6003811115611b3857611b38615122565b03611b95576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bef565b81358155611ba960408301602084016154f3565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611be957611be9615122565b02179055505b50505050565b611bfd611c7e565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c466033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611ce1816121c3565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d92576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611de657611de6615122565b6003811115611df757611df7615122565b9052509050600081602001516003811115611e1457611e14615122565b03611e4b576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190615545565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f609190615545565b835160ff54919250906001600160a01b031615801590612000575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612000919061555e565b15612009575060005b600061201d82670de0b6b3a764000061541d565b90508261202a8286615464565b61203491906154b8565b95508560018161204c670de0b6b3a76400008e615464565b612056919061541d565b61206091906154a1565b61206a91906154b8565b96505050505050935093915050565b6001600160a01b0381166120f55760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611250576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c954036122555760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b6000806122698585613fa0565b61227385886140c0565b9150612280828686610f71565b915050858110156122c7576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b6122d284848361420b565b9550959350505050565b60006122e784610c30565b6001600160a01b038516600090815261012d60205260408120549192509061231090849061541d565b905061231b81613074565b815160008080805b8481101561264357600061012e600089848151811061234457612344615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b031681526020019081526020016000205490508060001461263a576123a56001876154a1565b821015612405576123d18883815181106123c1576123c1615435565b60200260200101518c8b8a614285565b6123db908661541d565b9450866123e8828c615464565b6123f291906154b8565b93506123fe848461541d565b9250612500565b6000612411868b6154a1565b90508061012e60008b868151811061242b5761242b615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461248591906154a1565b925050819055508b6001600160a01b03168984815181106124a8576124a8615435565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce38836040516124ea91815260200190565b60405180910390a36124fc848c6154a1565b9450505b8b6001600160a01b031688838151811061251c5761251c615435565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af558760405161257d91815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125ae576125ae615435565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561262157600080fd5b505af1158015612635573d6000803e3d6000fd5b505050505b50600101612323565b5050505050505050505050565b600160c955565b612660816121c3565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6126dd816121c3565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab9061279d90339086906004016155d8565b602060405180830381865afa1580156127ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127de919061555e565b9050806114d3573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b939291906155fa565b84838114158061282d5750808214155b15612864576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612ae457600086868381811061288357612883615435565b90506020028101906128959190615626565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509394508892508791508590508181106128dd576128dd615435565b90506020028101906128ef9190615626565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508451835193945092831491506129629050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612ad55782818151811061297f5761297f615435565b602002602001015161013060008e8e8981811061299e5761299e615435565b90506020020160208101906129b39190614db1565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008684815181106129e7576129e7615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a3857612a38615435565b60200260200101516001600160a01b03168c8c87818110612a5b57612a5b615435565b9050602002016020810190612a709190614db1565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612aac57612aac615435565b6020026020010151604051612ac5911515815260200190565b60405180910390a3600101612965565b50836001019350505050612867565b5050505050505050565b600054610100900460ff16612b6b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612b748461435e565b612b7c6143ec565b611bef838383614471565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612be8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c1091908101906153b9565b805190915060005b81811015612d4b57828181518110612c3257612c32615435565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d0657846001600160a01b0316838281518110612c8e57612c8e615435565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf7919061568e565b6001600160a01b031614612d3c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d4b57600101612c18565b505050919050565b60008084600003612d90576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612de457612de4615122565b6003811115612df557612df5615122565b9052509050600081602001516003811115612e1257612e12615122565b03612e49576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ead573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed19190615545565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5e9190615545565b835160ff54919250906001600160a01b031615801590612ffe575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffe919061555e565b15613007575060005b600061301b82670de0b6b3a764000061541d565b905061302f670de0b6b3a764000084615464565b8161303a868d615464565b6130449190615464565b61304e91906154b8565b96508261305b8286615464565b61306591906154b8565b95505050505050935093915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561310e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131329190615545565b90508082111561316e576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d602052604081205461319290836154a1565b905082811015611bef5780830360006131aa86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b8281101561337e5761012e60008683815181106131ec576131ec615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133765761324a6001846154a1565b8110156132875761327685828151811061326657613266615435565b60200260200101518b8887614285565b613280908361541d565b9150613376565b600061329383886154a1565b90508061012e60008885815181106132ad576132ad615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461330791906154a1565b925050819055508a6001600160a01b031686838151811061332a5761332a615435565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161336c91815260200190565b60405180910390a3505b6001016131cd565b506001600160a01b038916600090815261012d6020526040812080548792906133a89084906154a1565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f6c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614536565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134ac576134a582612b87565b905061354b565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015613519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353d919061568e565b6001600160a01b0316141590505b92915050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556107018161461e565b61358b81613074565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b60006135d88383613461565b613621576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015613683573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a79190615545565b6001600160a01b038516600090815261012d602052604090205490915080821115613920576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff16156139205760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa158015613765573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137899190615545565b60fe549091506137a6906001600160a01b038681169116876133b8565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561380b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061382f9190615545565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac3537898961389a86866154a1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561390157600080fd5b505af1158015613915573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613933613f14565b60fe5460ff549192506001600160a01b03908116916000911615613db85760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156139c2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139ea91908101906156ab565b8151919350915060005b81811015613db357828181518110613a0e57613a0e615435565b602002602001015160000315613db3576000848281518110613a3257613a32615435565b60200260200101516001600160a01b0316636f1a30a8858481518110613a5a57613a5a615435565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613a9c939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ade9190615766565b91505088811115613aec5750875b613af6818b614688565b613b005750613db3565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b879190615545565b90508a6001600160a01b031663095ea7b3878581518110613baa57613baa615435565b6020026020010151846040518363ffffffff1660e01b8152600401613be49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c27919061555e565b50858381518110613c3a57613c3a615435565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ce89190615766565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d719190615545565b9050613d7d838c6154a1565b9a50613d8982826154a1565b613d93908961541d565b97508a600003613da557505050613db3565b8360010193505050506139f4565b505050505b61096b86848388886147c0565b600080613dd28585613fa0565b6000613ddf87878761107a565b91505087811115613e26576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e3086826140c0565b9250613e3d838787610f71565b9250613e4c905085858461420b565b509550959350505050565b600080613e648585613fa0565b6000613e7187878761107a565b915050613e7e86826140c0565b9250808314613eb9576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613efd576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f0885858961420b565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f9b919061568e565b905090565b60ff546000906001600160a01b03161580159061403d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015614019573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061403d919061555e565b905080158015614089575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff16600381111561408757614087615122565b145b15610f6c576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015614129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061414d9190615545565b60fe5490915061416c906001600160a01b03848116913391168761495e565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa1580156141d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141f59190615545565b905061420182826154a1565b9695505050505050565b6001600160a01b038316600090815261012d60205260409020548181101561425f576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61426984836149af565b8361427e6001600160a01b03821685856133b8565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142bb908590615464565b6142c591906154b8565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143029084906154a1565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161434e91815260200190565b60405180910390a3949350505050565b600054610100900460ff166143db5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6143e36149e1565b61070181614a66565b600054610100900460ff166144695760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614ae3565b600054610100900460ff166144ee5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6144f7836126d4565b61450082611cd8565b61450981613582565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b600061458b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b609092919063ffffffff16565b90508051600014806145ac5750808060200190518101906145ac919061555e565b610f6c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b1580156146e957600080fd5b505af11580156146fd573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa158015614771573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147959190615545565b61479f9190615464565b6147a991906154b8565b905060fb5481106147b957600191505b5092915050565b82156148975760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b15801561487e57600080fd5b505af1158015614892573d6000803e3d6000fd5b505050505b801561427e576001600160a01b038216600090815261012d6020526040812080548392906148c690849061541d565b90915550506001600160a01b03808616600090815261012e602090815260408083209386168352929052908120805483929061490390849061541d565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161494f91815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bef9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016133fd565b6001600160a01b038216600090815261012d6020526040812080548392906149d89084906154a1565b90915550505050565b600054610100900460ff16614a5e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614b79565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126505760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614b6f8484600085614bff565b90505b9392505050565b600054610100900460ff16614bf65760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61125033613551565b606082471015614c775760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614c93919061578a565b60006040518083038185875af1925050503d8060008114614cd0576040519150601f19603f3d011682016040523d82523d6000602084013e614cd5565b606091505b5091509150614ce687838387614cf3565b925050505b949350505050565b60608315614d62578251600003614d5b576001600160a01b0385163b614d5b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614ceb565b614ceb8383815115614d775781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157a6565b6001600160a01b038116811461070157600080fd5b8035610dc781614d91565b600060208284031215614dc357600080fd5b8135614b7281614d91565b600080600060608486031215614de357600080fd5b833592506020840135614df581614d91565b91506040840135614e0581614d91565b809150509250925092565b600080600080600060a08688031215614e2857600080fd5b85359450602086013593506040860135614e4181614d91565b92506060860135614e5181614d91565b91506080860135614e6181614d91565b809150509295509295909350565b60008060408385031215614e8257600080fd5b8235614e8d81614d91565b91506020830135614e9d81614d91565b809150509250929050565b60008083601f840112614eba57600080fd5b50813567ffffffffffffffff811115614ed257600080fd5b6020830191508360208260051b8501011115614eed57600080fd5b9250929050565b60008060008060008060608789031215614f0d57600080fd5b863567ffffffffffffffff80821115614f2557600080fd5b614f318a838b01614ea8565b90985096506020890135915080821115614f4a57600080fd5b614f568a838b01614ea8565b90965094506040890135915080821115614f6f57600080fd5b50614f7c89828a01614ea8565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fb057600080fd5b614fb98c614da6565b9a50614fc760208d01614da6565b9950614fd560408d01614da6565b9850614fe360608d01614da6565b975060808c0135965067ffffffffffffffff8060a08e0135111561500657600080fd5b6150168e60a08f01358f01614ea8565b909750955060c08d013581101561502c57600080fd5b61503c8e60c08f01358f01614ea8565b909550935060e08d013581101561505257600080fd5b506150638d60e08e01358e01614ea8565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150bc5783516001600160a01b031683529284019291840191600101615097565b50909695505050505050565b6000806000606084860312156150dd57600080fd5b83356150e881614d91565b925060208401356150f881614d91565b929592945050506040919091013590565b60006020828403121561511b57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110615188577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614b726020830184615151565b6000806000806000606086880312156151b857600080fd5b85356151c381614d91565b9450602086013567ffffffffffffffff808211156151e057600080fd5b6151ec89838a01614ea8565b9096509450604088013591508082111561520557600080fd5b818801915088601f83011261521957600080fd5b81358181111561522857600080fd5b8960208260061b850101111561523d57600080fd5b9699959850939650602001949392505050565b6000806000838503608081121561526657600080fd5b843561527181614d91565b9350602085013561528181614d91565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152b357600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715615319576153196152c1565b604052919050565b600067ffffffffffffffff82111561533b5761533b6152c1565b5060051b60200190565b600082601f83011261535657600080fd5b8151602061536b61536683615321565b6152f0565b82815260059290921b8401810191818101908684111561538a57600080fd5b8286015b848110156153ae5780516153a181614d91565b835291830191830161538e565b509695505050505050565b6000602082840312156153cb57600080fd5b815167ffffffffffffffff8111156153e257600080fd5b614ceb84828501615345565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615430576154306153ee565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561549c5761549c6153ee565b500290565b6000828210156154b3576154b36153ee565b500390565b6000826154ee577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561550557600080fd5b813560048110614b7257600080fd5b848152602081018490526080810161552f6040830185615151565b61553c6060830184615151565b95945050505050565b60006020828403121561555757600080fd5b5051919050565b60006020828403121561557057600080fd5b81518015158114614b7257600080fd5b60005b8381101561559b578181015183820152602001615583565b83811115611bef5750506000910152565b600081518084526155c4816020860160208601615580565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614b6f60408301846155ac565b60006001600160a01b0380861683528085166020840152506060604083015261553c60608301846155ac565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261565b57600080fd5b83018035915067ffffffffffffffff82111561567657600080fd5b6020019150600581901b3603821315614eed57600080fd5b6000602082840312156156a057600080fd5b8151614b7281614d91565b600080604083850312156156be57600080fd5b825167ffffffffffffffff808211156156d657600080fd5b6156e286838701615345565b93506020915081850151818111156156f957600080fd5b85019050601f8101861361570c57600080fd5b805161571a61536682615321565b81815260059190911b8201830190838101908883111561573957600080fd5b928401925b828410156157575783518252928401929084019061573e565b80955050505050509250929050565b6000806040838503121561577957600080fd5b505080516020909101519092909150565b6000825161579c818460208701615580565b9190910192915050565b602081526000614b7260208301846155ac56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a26469706673582212200c4c1be8186609d8812933be8513b877d4d7456c543e250549bac4e27cafee1364736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "e9f683aad829bf9574e4eef6b067ab3e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vBNB_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidArguments\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"MarketNotExistInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetsReservesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"name\":\"PoolAssetsDirectTransferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPoolRegistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPoolRegistry\",\"type\":\"address\"}],\"name\":\"PoolRegistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_COMPTROLLER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NATIVE_WRAPPED\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VBNB\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolAssetReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"getPools\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"poolsWithCore\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolsAssetsDirectTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"setPoolsAssetsDirectTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"errors\":{\"ReentrancyGuardError()\":[{\"details\":\"This error is used to safeguard against reentrancy attacks, ensuring that a certain operation cannot be called recursively within the same transaction.\"}]},\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Reserves of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"corePoolComptroller_\":\"Address of the Comptroller pool\",\"nativeWrapped_\":\"Address of the wrapped native currency\",\"vBNB_\":\"Address of the vBNB\"}},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getPoolAssetReserve(address,address)\":{\"custom:error\":\"MarketNotExistInPool When asset does not exist in the pool(comptroller)ReentrancyGuardError thrown to prevent reentrancy during the function execution\",\"details\":\"Get the Amount of the asset in the risk fund for the specific pool\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"},\"returns\":{\"reserves\":\"Asset's reserve in risk fund\"}},\"getPools(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"poolsWithCore\":\"Array of the pools addresses in which token is available\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256,address[],address[][],bool[][])\":{\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"minimum amount to convert\",\"poolRegistry_\":\"Address of the pool registry\",\"priceOracle_\":\"Resilient oracle address\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPoolRegistry(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"custom:event\":\"PoolRegistryUpdated emits on success\",\"details\":\"Pool registry setter\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"custom:access\":\"Restricted by ACM\",\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"stateVariables\":{\"CORE_POOL_COMPTROLLER\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"NATIVE_WRAPPED\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"VBNB\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\",\"details\":\"This address is used to include the BNB market while in getPools method\"},\"poolsAssetsDirectTransfer\":{\"details\":\"Comptroller(pool) -> Asset -> bool(should transfer directly on true)\"},\"poolsAssetsReserves\":{\"details\":\"Comptroller(pool) -> Asset -> amount\"}},\"title\":\"RiskFundConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"MarketNotExistInPool(address,address)\":[{\"notice\":\"thrown when asset does not exist in the pool\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"ReentrancyGuardError()\":[{\"notice\":\"thrown to prevent reentrancy\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Emitted after updating of the assets reserves amount -> reserve increased by amount\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDirectTransferUpdated(address,address,bool)\":{\"notice\":\"Emitted after the poolsAssetsDirectTransfer mapping is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_COMPTROLLER()\":{\"notice\":\"Address of the core pool comptroller\"},\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"NATIVE_WRAPPED()\":{\"notice\":\"Address of the native wrapped currency\"},\"VBNB()\":{\"notice\":\"Address of the vBNB\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\"},\"getPools(address)\":{\"notice\":\"Get the array of all pools addresses\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"poolRegistry()\":{\"notice\":\"Address of pool registry contract\"},\"poolsAssetsDirectTransfer(address,address)\":{\"notice\":\"The mapping contains the assets for each pool which are sent to RiskFund directly\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"notice\":\"Update the poolsAssetsDirectTransfer mapping\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"RiskFundConverter used for token conversions and sends received token to RiskFund\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/RiskFundConverter.sol\":\"RiskFundConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IComptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IComptroller {\\n function isComptroller() external view returns (bool);\\n\\n function markets(address) external view returns (bool);\\n\\n function getAllMarkets() external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x7d85db8d34103352b25f29f591c1e45159222f0d2bbafaa3fcd42f42bf9a523d\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IPoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IPoolRegistry {\\n /// @notice Get VToken in the Pool for an Asset\\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\\n\\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb38a3b61926e55588096e0657b758b178130386143a5658030d659038ec7075c\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IVToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IVToken {\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x0718e50835da441b2dddcf6d52a671c43d386b96dbcc9eb41d68c3647b82c117\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa =\\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\\n tokenInToOutConversion; //round-up\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa =\\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\\n (tokenOutUnderlyingPrice * EXP_SCALE);\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n\\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\\n converterNetwork.isTokenConverter(msg.sender);\\n if (isPrivateConversion) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n if (isPrivateConversion) {\\n amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion;\\n } else {\\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\\n }\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n}\\n\",\"keccak256\":\"0xdecdaf378a5af7744557fc29495d6db49c6900be1b03bcb6faa2b3a23c9a5c59\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/RiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\nimport { IPoolRegistry } from \\\"../Interfaces/IPoolRegistry.sol\\\";\\nimport { IComptroller } from \\\"../Interfaces/IComptroller.sol\\\";\\nimport { IRiskFund, IRiskFundGetters } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IVToken } from \\\"../Interfaces/IVToken.sol\\\";\\n\\n/// @title RiskFundConverter\\n/// @author Venus\\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the core pool comptroller\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable CORE_POOL_COMPTROLLER;\\n\\n ///@notice Address of the vBNB\\n ///@dev This address is used to include the BNB market while in getPools method\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable VBNB;\\n\\n ///@notice Address of the native wrapped currency\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable NATIVE_WRAPPED;\\n\\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\\n mapping(address => uint256) internal assetsReserves;\\n\\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\\n /// @dev Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\\n\\n /// @notice Address of pool registry contract\\n address public poolRegistry;\\n\\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\\n\\n /// @notice Emitted when pool registry address is updated\\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\\n\\n /// @notice Emitted after updating of the assets reserves\\n /// amount -> reserve increased by amount\\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\\n\\n // Error thrown when comptrollers array length is not equal to assets array length\\n error InvalidArguments();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice thrown when asset does not exist in the pool\\n error MarketNotExistInPool(address comptroller, address asset);\\n\\n /// @notice thrown to prevent reentrancy\\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\\n /// cannot be called recursively within the same transaction.\\n error ReentrancyGuardError();\\n\\n /// @param corePoolComptroller_ Address of the Comptroller pool\\n /// @param vBNB_ Address of the vBNB\\n /// @param nativeWrapped_ Address of the wrapped native currency\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address corePoolComptroller_,\\n address vBNB_,\\n address nativeWrapped_\\n ) {\\n ensureNonzeroAddress(corePoolComptroller_);\\n ensureNonzeroAddress(vBNB_);\\n ensureNonzeroAddress(nativeWrapped_);\\n\\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\\n VBNB = vBNB_;\\n NATIVE_WRAPPED = nativeWrapped_;\\n\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param poolRegistry_ Address of the pool registry\\n /// @param minAmountToConvert_ minimum amount to convert\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address poolRegistry_,\\n uint256 minAmountToConvert_,\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) public initializer {\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n ensureNonzeroAddress(poolRegistry_);\\n poolRegistry = poolRegistry_;\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Pool registry setter\\n /// @param poolRegistry_ Address of the pool registry\\n /// @custom:event PoolRegistryUpdated emits on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:access Only Governance\\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\\n ensureNonzeroAddress(poolRegistry_);\\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\\n poolRegistry = poolRegistry_;\\n }\\n\\n /// @notice Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:access Restricted by ACM\\n function setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) external {\\n _checkAccessAllowed(\\\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\\\");\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return reserves Asset's reserve in risk fund\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n reserves = poolsAssetsReserves[comptroller][asset];\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Reserves of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n tokenBalance = assetsReserves[tokenAddress];\\n }\\n\\n /// @notice Get the array of all pools addresses\\n /// @param tokenAddress Address of the token\\n /// @return poolsWithCore Array of the pools addresses in which token is available\\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\\n\\n if (isAssetListedInCore(tokenAddress)) {\\n uint256 poolsLength = poolsWithCore.length;\\n address[] memory extendedPools = new address[](poolsLength + 1);\\n\\n for (uint256 i; i < poolsLength; ) {\\n extendedPools[i] = poolsWithCore[i];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\\n poolsWithCore = extendedPools;\\n }\\n }\\n\\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\\n assetsReserves[tokenOutAddress] -= amountOut;\\n }\\n\\n /// @notice Hook to perform after converting tokens\\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\\n /// @param tokenInAddress Address of the tokenIn\\n /// @param tokenOutAddress Address of the tokenOut\\n /// @param amountIn Amount of tokenIn transferred\\n /// @param amountOut Amount of tokenOut transferred\\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\\n function _postConversionHook(\\n address tokenInAddress,\\n address tokenOutAddress,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal override {\\n address[] memory pools = getPools(tokenOutAddress);\\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\\n ensureNonzeroValue(assetReserve);\\n\\n uint256 poolsLength = pools.length;\\n uint256 distributedOutShare;\\n uint256 poolAmountInShare;\\n uint256 distributedInShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\\n if (currentPoolsAssetsReserves != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\\n distributedInShare += poolAmountInShare;\\n } else {\\n uint256 distributedDiff = amountOut - distributedOutShare;\\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\\n poolAmountInShare = amountIn - distributedInShare;\\n }\\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n\\n address[] memory pools = getPools(tokenAddress);\\n uint256 assetReserve = assetsReserves[tokenAddress];\\n uint256 poolsLength = pools.length;\\n uint256 distributedShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\\n } else {\\n uint256 distributedDiff = amountDiff - distributedShare;\\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n assetsReserves[tokenAddress] -= amountDiff;\\n }\\n }\\n\\n /// @dev Update the poolAssetsReserves upon transferring the tokens\\n /// @param pool Address of the pool\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @param assetReserve Asset's reserve for the pool\\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\\n /// @custom:event AssetsReservesUpdated emits on success\\n function updatePoolAssetsReserve(\\n address pool,\\n address tokenAddress,\\n uint256 amount,\\n uint256 assetReserve\\n ) internal returns (uint256 poolAmountShare) {\\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\\n }\\n\\n /// @dev Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\\n function _setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) internal {\\n uint256 comptrollersLength = comptrollers.length;\\n\\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 i; i < comptrollersLength; ) {\\n address[] memory poolAssets = assets[i];\\n bool[] memory assetsValues = values[i];\\n uint256 poolAssetsLength = poolAssets.length;\\n\\n if (poolAssetsLength != assetsValues.length) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 j; j < poolAssetsLength; ) {\\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\\n unchecked {\\n ++j;\\n }\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// and transferring funds to the protocol share reserve\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return balanceDifference Amount of asset, for _privateConversion\\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n function _updateAssetsState(address comptroller, address asset)\\n internal\\n override\\n returns (uint256 balanceDifference)\\n {\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 currentBalance = token.balanceOf(address(this));\\n uint256 assetReserve = assetsReserves[asset];\\n if (currentBalance > assetReserve) {\\n unchecked {\\n balanceDifference = currentBalance - assetReserve;\\n }\\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\\n token.safeTransfer(destinationAddress, balanceDifference);\\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\\n\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\\n IRiskFund(destinationAddress).updatePoolState(\\n comptroller,\\n asset,\\n newDestinationBalance - previousDestinationBalance\\n );\\n balanceDifference = 0;\\n }\\n }\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal override {\\n if (convertedTokenInBalance > 0) {\\n emit AssetTransferredToDestination(\\n destinationAddress,\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance\\n );\\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\\n }\\n if (convertedTokenOutBalance > 0) {\\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed in core pool or not\\n /// @param tokenAddress Address of the asset\\n /// @return isAssetListed true if the asset is listed\\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\\n\\n uint256 coreMarketsLength = coreMarkets.length;\\n for (uint256 i; i < coreMarketsLength; ) {\\n isAssetListed = (VBNB == coreMarkets[i])\\n ? (tokenAddress == NATIVE_WRAPPED)\\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\\n\\n if (isAssetListed) {\\n break;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed or not\\n /// @param comptroller Address of the comptroller\\n /// @param asset Address of the asset\\n /// @return isListed true if the asset is listed\\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\\n if (comptroller == CORE_POOL_COMPTROLLER) {\\n isListed = isAssetListedInCore(asset);\\n } else {\\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n }\\n\\n /// @dev Get base asset address of the RiskFund\\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\\n }\\n}\\n\",\"keccak256\":\"0xa9fda55440f25049f1946980b801723cf2111584253a1c11ac1bb7d773cbe39e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162005aba38038062005aba83398101604081905262000034916200018a565b6200003f8362000081565b6200004a8262000081565b620000558162000081565b6001600160a01b0380841660805282811660a052811660c05262000078620000ac565b505050620001d4565b6001600160a01b038116620000a9576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff1615620001195760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016b576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018557600080fd5b919050565b600080600060608486031215620001a057600080fd5b620001ab846200016d565b9250620001bb602085016200016d565b9150620001cb604085016200016d565b90509250925092565b60805160a05160c05161589362000227600039600081816103e20152612d3b0152600081816103bb0152612c780152600081816106c501528181610d7a01528181612bbf015261349801526158936000f3fe608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614de4565b6106f0565b005b61037b610376366004614e01565b610704565b60408051928352602083019190915201610315565b61036661039e366004614de4565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e43565b6107d0565b610343610425366004614ea2565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614de4565b61091a565b610366610467366004614de4565b61092b565b61036661047a366004614f27565b61093c565b61036661048d366004614fc1565b610973565b610366610b4a565b6104ad6104a8366004614de4565b610c30565b60405161031591906150ae565b61037b6104c8366004614e01565b610dcc565b6103666104db3660046150fb565b610eca565b61037b6104ee366004614e01565b610f71565b61037b610501366004614e01565b61107a565b610519610514366004614ea2565b611179565b604051908152602001610315565b610519610535366004614de4565b6001600160a01b0316600090815261012d602052604090205490565b61036661123e565b61036661056736600461513c565b611252565b610366611299565b610366610582366004614de4565b611324565b6033546001600160a01b0316610301565b61037b6105a6366004614e43565b6113ab565b6103666105b9366004614ea2565b6114a1565b61012f54610301906001600160a01b031681565b6106076105e0366004614ea2565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516103159291906151bf565b6097546001600160a01b0316610301565b61037b610634366004614e43565b6114d7565b6103666115cd565b61036661064f3660046151d3565b61167f565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e43565b61171d565b6103666106a8366004615283565b61184c565b6103666106bb366004614de4565b611bf5565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c7e565b61070181611cd8565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615155565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d55565b508092505050935093915050565b6107c7611c7e565b610701816120ac565b6000808285856107de6121a1565b6107e7836121f6565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610857612236565b6108648a8a8a8a8a61228f565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c7e565b6107018161268a565b610933611c7e565b61070181612707565b61095d6040518060600160405280603c8152602001615822603c9139612784565b61096b868686868686612850565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612b21565b610a97896121f6565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad9878787878787612850565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250612784565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153ec565b9050610cc882612bba565b15610dc75780516000610cdc826001615450565b67ffffffffffffffff811115610cf457610cf46152f4565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615468565b6020026020010151828281518110610d5757610d57615468565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615468565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615155565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d86565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ec05781600181610e9c670de0b6b3a764000085615497565b610ea69190615450565b610eb091906154d4565b610eba91906154eb565b93508092505b5050935093915050565b610ed2611c7e565b610eda612236565b610ee3836121f6565b610eec826121f6565b610ef5816130a7565b82610f0081836130e1565b610f146001600160a01b03821684846133eb565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f5991815260200190565b60405180910390a350610f6c600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561104d57600080fd5b505af1158015611061573d6000803e3d6000fd5b50505050611070858585612d86565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110de57600080fd5b505af11580156110f2573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561115657600080fd5b505af115801561116a573d6000803e3d6000fd5b50505050611070858585611d55565b600061118760c95460021490565b156111be576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c88383613494565b611211576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b611246611c7e565b6112506000613584565b565b6112906040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250612784565b610701816135b5565b60655433906001600160a01b0316811461131b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613584565b61132c611c7e565b611335816121f6565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113b96121a1565b6113c2836121f6565b816001600160a01b0316836001600160a01b031614806113f35750806001600160a01b0316836001600160a01b0316145b1561142a576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611432612236565b61143f8a8a8a8a8a61228f565b90955093506114508888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b6114a9612236565b60006114b583836135ff565b905080156114c8576114c883838361395c565b506114d3600160c955565b5050565b6000808285856114e56121a1565b6114ee836121f6565b816001600160a01b0316836001600160a01b0316148061151f5750806001600160a01b0316836001600160a01b0316145b15611556576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61155e612236565b61156b8a8a8a8a8a613df8565b909550935061157c8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b61160b6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250612784565b6116136121a1565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116b9576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156117145761170c878787848181106116da576116da615468565b90506020020160208101906116ef9190614de4565b86868581811061170157611701615468565b90506040020161184c565b6001016116bc565b50505050505050565b60008082858561172b6121a1565b611734836121f6565b816001600160a01b0316836001600160a01b031614806117655750806001600160a01b0316836001600160a01b0316145b1561179c576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117a4612236565b6117b18a8a8a8a8a613e8a565b90955093508884146117ef576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117fb8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b61186d6040518060600160405280603581526020016157ed60359139612784565b611876836121f6565b61187f826121f6565b6706f05b59d3b20000813511156118d3576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b0316148061190c57506118f6613f47565b6001600160a01b0316836001600160a01b031614155b80611954575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561195157611951615155565b14155b1561198b576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261199d6040830160208401615526565b60038111156119ae576119ae615155565b1480156119bb5750803515155b156119f2576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002611a046040830160208401615526565b6003811115611a1557611a15615155565b1480611a4157506001611a2e6040830160208401615526565b6003811115611a3f57611a3f615155565b145b8015611a56575060ff546001600160a01b0316155b15611a8d576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611afd91908a01908a01615526565b604051611b0d9493929190615547565b60405180910390a36000611b276040840160208501615526565b6003811115611b3857611b38615155565b03611b95576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bef565b81358155611ba96040830160208401615526565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611be957611be9615155565b02179055505b50505050565b611bfd611c7e565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c466033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611ce1816121f6565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d92576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611de657611de6615155565b6003811115611df757611df7615155565b9052509050600081602001516003811115611e1457611e14615155565b03611e4b576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190615578565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f609190615578565b835160ff54919250906000906001600160a01b031615801590612003575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120039190615591565b9050801561201057600091505b600061202483670de0b6b3a7640000615450565b9050836120318287615497565b61203b91906154eb565b965081156120675786612056670de0b6b3a76400008d615497565b61206091906154eb565b975061209e565b8660018161207d670de0b6b3a76400008f615497565b6120879190615450565b61209191906154d4565b61209b91906154eb565b97505b505050505050935093915050565b6001600160a01b0381166121285760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611250576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c954036122885760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b60008061229c8585613fd3565b6122a685886140f3565b91506122b3828686610f71565b915050858110156122fa576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b61230584848361423e565b9550959350505050565b600061231a84610c30565b6001600160a01b038516600090815261012d602052604081205491925090612343908490615450565b905061234e816130a7565b815160008080805b8481101561267657600061012e600089848151811061237757612377615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b031681526020019081526020016000205490508060001461266d576123d86001876154d4565b821015612438576124048883815181106123f4576123f4615468565b60200260200101518c8b8a6142b8565b61240e9086615450565b94508661241b828c615497565b61242591906154eb565b93506124318484615450565b9250612533565b6000612444868b6154d4565b90508061012e60008b868151811061245e5761245e615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546124b891906154d4565b925050819055508b6001600160a01b03168984815181106124db576124db615468565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161251d91815260200190565b60405180910390a361252f848c6154d4565b9450505b8b6001600160a01b031688838151811061254f5761254f615468565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af55876040516125b091815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125e1576125e1615468565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561265457600080fd5b505af1158015612668573d6000803e3d6000fd5b505050505b50600101612356565b5050505050505050505050565b600160c955565b612693816121f6565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b612710816121f6565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906127d0903390869060040161560b565b602060405180830381865afa1580156127ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128119190615591565b9050806114d3573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b9392919061562d565b8483811415806128605750808214155b15612897576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b175760008686838181106128b6576128b6615468565b90506020028101906128c89190615659565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945088925087915085905081811061291057612910615468565b90506020028101906129229190615659565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508451835193945092831491506129959050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b08578281815181106129b2576129b2615468565b602002602001015161013060008e8e898181106129d1576129d1615468565b90506020020160208101906129e69190614de4565b6001600160a01b03166001600160a01b031681526020019081526020016000206000868481518110612a1a57612a1a615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a6b57612a6b615468565b60200260200101516001600160a01b03168c8c87818110612a8e57612a8e615468565b9050602002016020810190612aa39190614de4565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612adf57612adf615468565b6020026020010151604051612af8911515815260200190565b60405180910390a3600101612998565b5083600101935050505061289a565b5050505050505050565b600054610100900460ff16612b9e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612ba784614391565b612baf61441f565b611bef8383836144a4565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612c1b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c4391908101906153ec565b805190915060005b81811015612d7e57828181518110612c6557612c65615468565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d3957846001600160a01b0316838281518110612cc157612cc1615468565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d2a91906156c1565b6001600160a01b031614612d6f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d7e57600101612c4b565b505050919050565b60008084600003612dc3576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612e1757612e17615155565b6003811115612e2857612e28615155565b9052509050600081602001516003811115612e4557612e45615155565b03612e7c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ee0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f049190615578565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f919190615578565b835160ff54919250906001600160a01b031615801590613031575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa15801561300d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130319190615591565b1561303a575060005b600061304e82670de0b6b3a7640000615450565b9050613062670de0b6b3a764000084615497565b8161306d868d615497565b6130779190615497565b61308191906154eb565b96508261308e8286615497565b61309891906154eb565b95505050505050935093915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015613141573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131659190615578565b9050808211156131a1576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d60205260408120546131c590836154d4565b905082811015611bef5780830360006131dd86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b828110156133b15761012e600086838151811061321f5761321f615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133a95761327d6001846154d4565b8110156132ba576132a985828151811061329957613299615468565b60200260200101518b88876142b8565b6132b39083615450565b91506133a9565b60006132c683886154d4565b90508061012e60008885815181106132e0576132e0615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461333a91906154d4565b925050819055508a6001600160a01b031686838151811061335d5761335d615468565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161339f91815260200190565b60405180910390a3505b600101613200565b506001600160a01b038916600090815261012d6020526040812080548792906133db9084906154d4565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f6c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614569565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134df576134d882612bba565b905061357e565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa15801561354c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357091906156c1565b6001600160a01b0316141590505b92915050565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561070181614651565b6135be816130a7565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b600061360b8383613494565b613654576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156136b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136da9190615578565b6001600160a01b038516600090815261012d602052604090205490915080821115613953576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff16156139535760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa158015613798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bc9190615578565b60fe549091506137d9906001600160a01b038681169116876133eb565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561383e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138629190615578565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac353789896138cd86866154d4565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561393457600080fd5b505af1158015613948573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613966613f47565b60fe5460ff549192506001600160a01b03908116916000911615613deb5760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156139f5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a1d91908101906156de565b8151919350915060005b81811015613de657828181518110613a4157613a41615468565b602002602001015160000315613de6576000848281518110613a6557613a65615468565b60200260200101516001600160a01b0316636f1a30a8858481518110613a8d57613a8d615468565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613acf939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b119190615799565b91505088811115613b1f5750875b613b29818b6146bb565b613b335750613de6565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bba9190615578565b90508a6001600160a01b031663095ea7b3878581518110613bdd57613bdd615468565b6020026020010151846040518363ffffffff1660e01b8152600401613c179291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c5a9190615591565b50858381518110613c6d57613c6d615468565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613cf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d1b9190615799565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613da49190615578565b9050613db0838c6154d4565b9a50613dbc82826154d4565b613dc69089615450565b97508a600003613dd857505050613de6565b836001019350505050613a27565b505050505b61096b86848388886147f3565b600080613e058585613fd3565b6000613e1287878761107a565b91505087811115613e59576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e6386826140f3565b9250613e70838787610f71565b9250613e7f905085858461423e565b509550959350505050565b600080613e978585613fd3565b6000613ea487878761107a565b915050613eb186826140f3565b9250808314613eec576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613f30576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f3b85858961423e565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613faa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fce91906156c1565b905090565b60ff546000906001600160a01b031615801590614070575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa15801561404c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140709190615591565b9050801580156140bc575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff1660038111156140ba576140ba615155565b145b15610f6c576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa15801561415c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141809190615578565b60fe5490915061419f906001600160a01b038481169133911687614991565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015614204573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142289190615578565b905061423482826154d4565b9695505050505050565b6001600160a01b038316600090815261012d602052604090205481811015614292576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61429c84836149e2565b836142b16001600160a01b03821685856133eb565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142ee908590615497565b6142f891906154eb565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143359084906154d4565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161438191815260200190565b60405180910390a3949350505050565b600054610100900460ff1661440e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614416614a14565b61070181614a99565b600054610100900460ff1661449c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614b16565b600054610100900460ff166145215760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61452a83612707565b61453382611cd8565b61453c816135b5565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b60006145be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b939092919063ffffffff16565b90508051600014806145df5750808060200190518101906145df9190615591565b610f6c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561471c57600080fd5b505af1158015614730573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156147a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147c89190615578565b6147d29190615497565b6147dc91906154eb565b905060fb5481106147ec57600191505b5092915050565b82156148ca5760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b1580156148b157600080fd5b505af11580156148c5573d6000803e3d6000fd5b505050505b80156142b1576001600160a01b038216600090815261012d6020526040812080548392906148f9908490615450565b90915550506001600160a01b03808616600090815261012e6020908152604080832093861683529290529081208054839290614936908490615450565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161498291815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bef9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401613430565b6001600160a01b038216600090815261012d602052604081208054839290614a0b9084906154d4565b90915550505050565b600054610100900460ff16614a915760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614bac565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126835760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614ba28484600085614c32565b90505b9392505050565b600054610100900460ff16614c295760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61125033613584565b606082471015614caa5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614cc691906157bd565b60006040518083038185875af1925050503d8060008114614d03576040519150601f19603f3d011682016040523d82523d6000602084013e614d08565b606091505b5091509150614d1987838387614d26565b925050505b949350505050565b60608315614d95578251600003614d8e576001600160a01b0385163b614d8e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614d1e565b614d1e8383815115614daa5781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157d9565b6001600160a01b038116811461070157600080fd5b8035610dc781614dc4565b600060208284031215614df657600080fd5b8135614ba581614dc4565b600080600060608486031215614e1657600080fd5b833592506020840135614e2881614dc4565b91506040840135614e3881614dc4565b809150509250925092565b600080600080600060a08688031215614e5b57600080fd5b85359450602086013593506040860135614e7481614dc4565b92506060860135614e8481614dc4565b91506080860135614e9481614dc4565b809150509295509295909350565b60008060408385031215614eb557600080fd5b8235614ec081614dc4565b91506020830135614ed081614dc4565b809150509250929050565b60008083601f840112614eed57600080fd5b50813567ffffffffffffffff811115614f0557600080fd5b6020830191508360208260051b8501011115614f2057600080fd5b9250929050565b60008060008060008060608789031215614f4057600080fd5b863567ffffffffffffffff80821115614f5857600080fd5b614f648a838b01614edb565b90985096506020890135915080821115614f7d57600080fd5b614f898a838b01614edb565b90965094506040890135915080821115614fa257600080fd5b50614faf89828a01614edb565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fe357600080fd5b614fec8c614dd9565b9a50614ffa60208d01614dd9565b995061500860408d01614dd9565b985061501660608d01614dd9565b975060808c0135965067ffffffffffffffff8060a08e0135111561503957600080fd5b6150498e60a08f01358f01614edb565b909750955060c08d013581101561505f57600080fd5b61506f8e60c08f01358f01614edb565b909550935060e08d013581101561508557600080fd5b506150968d60e08e01358e01614edb565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150ef5783516001600160a01b0316835292840192918401916001016150ca565b50909695505050505050565b60008060006060848603121561511057600080fd5b833561511b81614dc4565b9250602084013561512b81614dc4565b929592945050506040919091013590565b60006020828403121561514e57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106151bb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614ba56020830184615184565b6000806000806000606086880312156151eb57600080fd5b85356151f681614dc4565b9450602086013567ffffffffffffffff8082111561521357600080fd5b61521f89838a01614edb565b9096509450604088013591508082111561523857600080fd5b818801915088601f83011261524c57600080fd5b81358181111561525b57600080fd5b8960208260061b850101111561527057600080fd5b9699959850939650602001949392505050565b6000806000838503608081121561529957600080fd5b84356152a481614dc4565b935060208501356152b481614dc4565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152e657600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561534c5761534c6152f4565b604052919050565b600067ffffffffffffffff82111561536e5761536e6152f4565b5060051b60200190565b600082601f83011261538957600080fd5b8151602061539e61539983615354565b615323565b82815260059290921b840181019181810190868411156153bd57600080fd5b8286015b848110156153e15780516153d481614dc4565b83529183019183016153c1565b509695505050505050565b6000602082840312156153fe57600080fd5b815167ffffffffffffffff81111561541557600080fd5b614d1e84828501615378565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561546357615463615421565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156154cf576154cf615421565b500290565b6000828210156154e6576154e6615421565b500390565b600082615521577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561553857600080fd5b813560048110614ba557600080fd5b84815260208101849052608081016155626040830185615184565b61556f6060830184615184565b95945050505050565b60006020828403121561558a57600080fd5b5051919050565b6000602082840312156155a357600080fd5b81518015158114614ba557600080fd5b60005b838110156155ce5781810151838201526020016155b6565b83811115611bef5750506000910152565b600081518084526155f78160208601602086016155b3565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614ba260408301846155df565b60006001600160a01b0380861683528085166020840152506060604083015261556f60608301846155df565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261568e57600080fd5b83018035915067ffffffffffffffff8211156156a957600080fd5b6020019150600581901b3603821315614f2057600080fd5b6000602082840312156156d357600080fd5b8151614ba581614dc4565b600080604083850312156156f157600080fd5b825167ffffffffffffffff8082111561570957600080fd5b61571586838701615378565b935060209150818501518181111561572c57600080fd5b85019050601f8101861361573f57600080fd5b805161574d61539982615354565b81815260059190911b8201830190838101908883111561576c57600080fd5b928401925b8284101561578a57835182529284019290840190615771565b80955050505050509250929050565b600080604083850312156157ac57600080fd5b505080516020909101519092909150565b600082516157cf8184602087016155b3565b9190910192915050565b602081526000614ba560208301846155df56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a2646970667358221220e9d437e5c5c1c0182f6a30b0ea44454a90e7075c47dc98b514a6b238801ce2d364736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614de4565b6106f0565b005b61037b610376366004614e01565b610704565b60408051928352602083019190915201610315565b61036661039e366004614de4565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e43565b6107d0565b610343610425366004614ea2565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614de4565b61091a565b610366610467366004614de4565b61092b565b61036661047a366004614f27565b61093c565b61036661048d366004614fc1565b610973565b610366610b4a565b6104ad6104a8366004614de4565b610c30565b60405161031591906150ae565b61037b6104c8366004614e01565b610dcc565b6103666104db3660046150fb565b610eca565b61037b6104ee366004614e01565b610f71565b61037b610501366004614e01565b61107a565b610519610514366004614ea2565b611179565b604051908152602001610315565b610519610535366004614de4565b6001600160a01b0316600090815261012d602052604090205490565b61036661123e565b61036661056736600461513c565b611252565b610366611299565b610366610582366004614de4565b611324565b6033546001600160a01b0316610301565b61037b6105a6366004614e43565b6113ab565b6103666105b9366004614ea2565b6114a1565b61012f54610301906001600160a01b031681565b6106076105e0366004614ea2565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516103159291906151bf565b6097546001600160a01b0316610301565b61037b610634366004614e43565b6114d7565b6103666115cd565b61036661064f3660046151d3565b61167f565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e43565b61171d565b6103666106a8366004615283565b61184c565b6103666106bb366004614de4565b611bf5565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c7e565b61070181611cd8565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615155565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d55565b508092505050935093915050565b6107c7611c7e565b610701816120ac565b6000808285856107de6121a1565b6107e7836121f6565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610857612236565b6108648a8a8a8a8a61228f565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c7e565b6107018161268a565b610933611c7e565b61070181612707565b61095d6040518060600160405280603c8152602001615822603c9139612784565b61096b868686868686612850565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612b21565b610a97896121f6565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad9878787878787612850565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250612784565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153ec565b9050610cc882612bba565b15610dc75780516000610cdc826001615450565b67ffffffffffffffff811115610cf457610cf46152f4565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615468565b6020026020010151828281518110610d5757610d57615468565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615468565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615155565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d86565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ec05781600181610e9c670de0b6b3a764000085615497565b610ea69190615450565b610eb091906154d4565b610eba91906154eb565b93508092505b5050935093915050565b610ed2611c7e565b610eda612236565b610ee3836121f6565b610eec826121f6565b610ef5816130a7565b82610f0081836130e1565b610f146001600160a01b03821684846133eb565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f5991815260200190565b60405180910390a350610f6c600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561104d57600080fd5b505af1158015611061573d6000803e3d6000fd5b50505050611070858585612d86565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110de57600080fd5b505af11580156110f2573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561115657600080fd5b505af115801561116a573d6000803e3d6000fd5b50505050611070858585611d55565b600061118760c95460021490565b156111be576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c88383613494565b611211576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b611246611c7e565b6112506000613584565b565b6112906040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250612784565b610701816135b5565b60655433906001600160a01b0316811461131b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613584565b61132c611c7e565b611335816121f6565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113b96121a1565b6113c2836121f6565b816001600160a01b0316836001600160a01b031614806113f35750806001600160a01b0316836001600160a01b0316145b1561142a576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611432612236565b61143f8a8a8a8a8a61228f565b90955093506114508888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b6114a9612236565b60006114b583836135ff565b905080156114c8576114c883838361395c565b506114d3600160c955565b5050565b6000808285856114e56121a1565b6114ee836121f6565b816001600160a01b0316836001600160a01b0316148061151f5750806001600160a01b0316836001600160a01b0316145b15611556576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61155e612236565b61156b8a8a8a8a8a613df8565b909550935061157c8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b61160b6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250612784565b6116136121a1565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116b9576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156117145761170c878787848181106116da576116da615468565b90506020020160208101906116ef9190614de4565b86868581811061170157611701615468565b90506040020161184c565b6001016116bc565b50505050505050565b60008082858561172b6121a1565b611734836121f6565b816001600160a01b0316836001600160a01b031614806117655750806001600160a01b0316836001600160a01b0316145b1561179c576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117a4612236565b6117b18a8a8a8a8a613e8a565b90955093508884146117ef576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117fb8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b61186d6040518060600160405280603581526020016157ed60359139612784565b611876836121f6565b61187f826121f6565b6706f05b59d3b20000813511156118d3576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b0316148061190c57506118f6613f47565b6001600160a01b0316836001600160a01b031614155b80611954575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561195157611951615155565b14155b1561198b576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261199d6040830160208401615526565b60038111156119ae576119ae615155565b1480156119bb5750803515155b156119f2576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002611a046040830160208401615526565b6003811115611a1557611a15615155565b1480611a4157506001611a2e6040830160208401615526565b6003811115611a3f57611a3f615155565b145b8015611a56575060ff546001600160a01b0316155b15611a8d576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611afd91908a01908a01615526565b604051611b0d9493929190615547565b60405180910390a36000611b276040840160208501615526565b6003811115611b3857611b38615155565b03611b95576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bef565b81358155611ba96040830160208401615526565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611be957611be9615155565b02179055505b50505050565b611bfd611c7e565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c466033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611ce1816121f6565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d92576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611de657611de6615155565b6003811115611df757611df7615155565b9052509050600081602001516003811115611e1457611e14615155565b03611e4b576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190615578565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f609190615578565b835160ff54919250906000906001600160a01b031615801590612003575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120039190615591565b9050801561201057600091505b600061202483670de0b6b3a7640000615450565b9050836120318287615497565b61203b91906154eb565b965081156120675786612056670de0b6b3a76400008d615497565b61206091906154eb565b975061209e565b8660018161207d670de0b6b3a76400008f615497565b6120879190615450565b61209191906154d4565b61209b91906154eb565b97505b505050505050935093915050565b6001600160a01b0381166121285760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611250576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c954036122885760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b60008061229c8585613fd3565b6122a685886140f3565b91506122b3828686610f71565b915050858110156122fa576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b61230584848361423e565b9550959350505050565b600061231a84610c30565b6001600160a01b038516600090815261012d602052604081205491925090612343908490615450565b905061234e816130a7565b815160008080805b8481101561267657600061012e600089848151811061237757612377615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b031681526020019081526020016000205490508060001461266d576123d86001876154d4565b821015612438576124048883815181106123f4576123f4615468565b60200260200101518c8b8a6142b8565b61240e9086615450565b94508661241b828c615497565b61242591906154eb565b93506124318484615450565b9250612533565b6000612444868b6154d4565b90508061012e60008b868151811061245e5761245e615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546124b891906154d4565b925050819055508b6001600160a01b03168984815181106124db576124db615468565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161251d91815260200190565b60405180910390a361252f848c6154d4565b9450505b8b6001600160a01b031688838151811061254f5761254f615468565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af55876040516125b091815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125e1576125e1615468565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561265457600080fd5b505af1158015612668573d6000803e3d6000fd5b505050505b50600101612356565b5050505050505050505050565b600160c955565b612693816121f6565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b612710816121f6565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906127d0903390869060040161560b565b602060405180830381865afa1580156127ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128119190615591565b9050806114d3573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b9392919061562d565b8483811415806128605750808214155b15612897576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b175760008686838181106128b6576128b6615468565b90506020028101906128c89190615659565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945088925087915085905081811061291057612910615468565b90506020028101906129229190615659565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508451835193945092831491506129959050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b08578281815181106129b2576129b2615468565b602002602001015161013060008e8e898181106129d1576129d1615468565b90506020020160208101906129e69190614de4565b6001600160a01b03166001600160a01b031681526020019081526020016000206000868481518110612a1a57612a1a615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a6b57612a6b615468565b60200260200101516001600160a01b03168c8c87818110612a8e57612a8e615468565b9050602002016020810190612aa39190614de4565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612adf57612adf615468565b6020026020010151604051612af8911515815260200190565b60405180910390a3600101612998565b5083600101935050505061289a565b5050505050505050565b600054610100900460ff16612b9e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612ba784614391565b612baf61441f565b611bef8383836144a4565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612c1b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c4391908101906153ec565b805190915060005b81811015612d7e57828181518110612c6557612c65615468565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d3957846001600160a01b0316838281518110612cc157612cc1615468565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d2a91906156c1565b6001600160a01b031614612d6f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d7e57600101612c4b565b505050919050565b60008084600003612dc3576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612e1757612e17615155565b6003811115612e2857612e28615155565b9052509050600081602001516003811115612e4557612e45615155565b03612e7c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ee0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f049190615578565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f919190615578565b835160ff54919250906001600160a01b031615801590613031575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa15801561300d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130319190615591565b1561303a575060005b600061304e82670de0b6b3a7640000615450565b9050613062670de0b6b3a764000084615497565b8161306d868d615497565b6130779190615497565b61308191906154eb565b96508261308e8286615497565b61309891906154eb565b95505050505050935093915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015613141573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131659190615578565b9050808211156131a1576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d60205260408120546131c590836154d4565b905082811015611bef5780830360006131dd86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b828110156133b15761012e600086838151811061321f5761321f615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133a95761327d6001846154d4565b8110156132ba576132a985828151811061329957613299615468565b60200260200101518b88876142b8565b6132b39083615450565b91506133a9565b60006132c683886154d4565b90508061012e60008885815181106132e0576132e0615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461333a91906154d4565b925050819055508a6001600160a01b031686838151811061335d5761335d615468565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161339f91815260200190565b60405180910390a3505b600101613200565b506001600160a01b038916600090815261012d6020526040812080548792906133db9084906154d4565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f6c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614569565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134df576134d882612bba565b905061357e565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa15801561354c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357091906156c1565b6001600160a01b0316141590505b92915050565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561070181614651565b6135be816130a7565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b600061360b8383613494565b613654576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156136b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136da9190615578565b6001600160a01b038516600090815261012d602052604090205490915080821115613953576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff16156139535760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa158015613798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bc9190615578565b60fe549091506137d9906001600160a01b038681169116876133eb565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561383e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138629190615578565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac353789896138cd86866154d4565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561393457600080fd5b505af1158015613948573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613966613f47565b60fe5460ff549192506001600160a01b03908116916000911615613deb5760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156139f5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a1d91908101906156de565b8151919350915060005b81811015613de657828181518110613a4157613a41615468565b602002602001015160000315613de6576000848281518110613a6557613a65615468565b60200260200101516001600160a01b0316636f1a30a8858481518110613a8d57613a8d615468565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613acf939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b119190615799565b91505088811115613b1f5750875b613b29818b6146bb565b613b335750613de6565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bba9190615578565b90508a6001600160a01b031663095ea7b3878581518110613bdd57613bdd615468565b6020026020010151846040518363ffffffff1660e01b8152600401613c179291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c5a9190615591565b50858381518110613c6d57613c6d615468565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613cf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d1b9190615799565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613da49190615578565b9050613db0838c6154d4565b9a50613dbc82826154d4565b613dc69089615450565b97508a600003613dd857505050613de6565b836001019350505050613a27565b505050505b61096b86848388886147f3565b600080613e058585613fd3565b6000613e1287878761107a565b91505087811115613e59576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e6386826140f3565b9250613e70838787610f71565b9250613e7f905085858461423e565b509550959350505050565b600080613e978585613fd3565b6000613ea487878761107a565b915050613eb186826140f3565b9250808314613eec576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613f30576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f3b85858961423e565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613faa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fce91906156c1565b905090565b60ff546000906001600160a01b031615801590614070575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa15801561404c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140709190615591565b9050801580156140bc575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff1660038111156140ba576140ba615155565b145b15610f6c576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa15801561415c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141809190615578565b60fe5490915061419f906001600160a01b038481169133911687614991565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015614204573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142289190615578565b905061423482826154d4565b9695505050505050565b6001600160a01b038316600090815261012d602052604090205481811015614292576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61429c84836149e2565b836142b16001600160a01b03821685856133eb565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142ee908590615497565b6142f891906154eb565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143359084906154d4565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161438191815260200190565b60405180910390a3949350505050565b600054610100900460ff1661440e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614416614a14565b61070181614a99565b600054610100900460ff1661449c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614b16565b600054610100900460ff166145215760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61452a83612707565b61453382611cd8565b61453c816135b5565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b60006145be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b939092919063ffffffff16565b90508051600014806145df5750808060200190518101906145df9190615591565b610f6c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561471c57600080fd5b505af1158015614730573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156147a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147c89190615578565b6147d29190615497565b6147dc91906154eb565b905060fb5481106147ec57600191505b5092915050565b82156148ca5760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b1580156148b157600080fd5b505af11580156148c5573d6000803e3d6000fd5b505050505b80156142b1576001600160a01b038216600090815261012d6020526040812080548392906148f9908490615450565b90915550506001600160a01b03808616600090815261012e6020908152604080832093861683529290529081208054839290614936908490615450565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161498291815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bef9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401613430565b6001600160a01b038216600090815261012d602052604081208054839290614a0b9084906154d4565b90915550505050565b600054610100900460ff16614a915760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614bac565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126835760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614ba28484600085614c32565b90505b9392505050565b600054610100900460ff16614c295760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61125033613584565b606082471015614caa5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614cc691906157bd565b60006040518083038185875af1925050503d8060008114614d03576040519150601f19603f3d011682016040523d82523d6000602084013e614d08565b606091505b5091509150614d1987838387614d26565b925050505b949350505050565b60608315614d95578251600003614d8e576001600160a01b0385163b614d8e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614d1e565b614d1e8383815115614daa5781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157d9565b6001600160a01b038116811461070157600080fd5b8035610dc781614dc4565b600060208284031215614df657600080fd5b8135614ba581614dc4565b600080600060608486031215614e1657600080fd5b833592506020840135614e2881614dc4565b91506040840135614e3881614dc4565b809150509250925092565b600080600080600060a08688031215614e5b57600080fd5b85359450602086013593506040860135614e7481614dc4565b92506060860135614e8481614dc4565b91506080860135614e9481614dc4565b809150509295509295909350565b60008060408385031215614eb557600080fd5b8235614ec081614dc4565b91506020830135614ed081614dc4565b809150509250929050565b60008083601f840112614eed57600080fd5b50813567ffffffffffffffff811115614f0557600080fd5b6020830191508360208260051b8501011115614f2057600080fd5b9250929050565b60008060008060008060608789031215614f4057600080fd5b863567ffffffffffffffff80821115614f5857600080fd5b614f648a838b01614edb565b90985096506020890135915080821115614f7d57600080fd5b614f898a838b01614edb565b90965094506040890135915080821115614fa257600080fd5b50614faf89828a01614edb565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fe357600080fd5b614fec8c614dd9565b9a50614ffa60208d01614dd9565b995061500860408d01614dd9565b985061501660608d01614dd9565b975060808c0135965067ffffffffffffffff8060a08e0135111561503957600080fd5b6150498e60a08f01358f01614edb565b909750955060c08d013581101561505f57600080fd5b61506f8e60c08f01358f01614edb565b909550935060e08d013581101561508557600080fd5b506150968d60e08e01358e01614edb565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150ef5783516001600160a01b0316835292840192918401916001016150ca565b50909695505050505050565b60008060006060848603121561511057600080fd5b833561511b81614dc4565b9250602084013561512b81614dc4565b929592945050506040919091013590565b60006020828403121561514e57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106151bb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614ba56020830184615184565b6000806000806000606086880312156151eb57600080fd5b85356151f681614dc4565b9450602086013567ffffffffffffffff8082111561521357600080fd5b61521f89838a01614edb565b9096509450604088013591508082111561523857600080fd5b818801915088601f83011261524c57600080fd5b81358181111561525b57600080fd5b8960208260061b850101111561527057600080fd5b9699959850939650602001949392505050565b6000806000838503608081121561529957600080fd5b84356152a481614dc4565b935060208501356152b481614dc4565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152e657600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561534c5761534c6152f4565b604052919050565b600067ffffffffffffffff82111561536e5761536e6152f4565b5060051b60200190565b600082601f83011261538957600080fd5b8151602061539e61539983615354565b615323565b82815260059290921b840181019181810190868411156153bd57600080fd5b8286015b848110156153e15780516153d481614dc4565b83529183019183016153c1565b509695505050505050565b6000602082840312156153fe57600080fd5b815167ffffffffffffffff81111561541557600080fd5b614d1e84828501615378565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561546357615463615421565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156154cf576154cf615421565b500290565b6000828210156154e6576154e6615421565b500390565b600082615521577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561553857600080fd5b813560048110614ba557600080fd5b84815260208101849052608081016155626040830185615184565b61556f6060830184615184565b95945050505050565b60006020828403121561558a57600080fd5b5051919050565b6000602082840312156155a357600080fd5b81518015158114614ba557600080fd5b60005b838110156155ce5781810151838201526020016155b6565b83811115611bef5750506000910152565b600081518084526155f78160208601602086016155b3565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614ba260408301846155df565b60006001600160a01b0380861683528085166020840152506060604083015261556f60608301846155df565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261568e57600080fd5b83018035915067ffffffffffffffff8211156156a957600080fd5b6020019150600581901b3603821315614f2057600080fd5b6000602082840312156156d357600080fd5b8151614ba581614dc4565b600080604083850312156156f157600080fd5b825167ffffffffffffffff8082111561570957600080fd5b61571586838701615378565b935060209150818501518181111561572c57600080fd5b85019050601f8101861361573f57600080fd5b805161574d61539982615354565b81815260059190911b8201830190838101908883111561576c57600080fd5b928401925b8284101561578a57835182529284019290840190615771565b80955050505050509250929050565b600080604083850312156157ac57600080fd5b505080516020909101519092909150565b600082516157cf8184602087016155b3565b9190910192915050565b602081526000614ba560208301846155df56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a2646970667358221220e9d437e5c5c1c0182f6a30b0ea44454a90e7075c47dc98b514a6b238801ce2d364736f6c634300080d0033", "devdoc": { "author": "Venus", "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", @@ -2192,7 +2192,7 @@ "notice": "To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)" }, "getAmountOut(uint256,address,address)": { - "notice": "To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)" + "notice": "To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut" }, "getPools(address)": { "notice": "Get the array of all pools addresses" @@ -2367,7 +2367,7 @@ "label": "conversionConfigurations", "offset": 0, "slot": "253", - "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5463_storage))" + "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5478_storage))" }, { "astId": 3371, @@ -2402,7 +2402,7 @@ "type": "t_array(t_uint256)45_storage" }, { - "astId": 5689, + "astId": 5704, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "assetsReserves", "offset": 0, @@ -2410,7 +2410,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5696, + "astId": 5711, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "poolsAssetsReserves", "offset": 0, @@ -2418,7 +2418,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 5699, + "astId": 5714, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "poolRegistry", "offset": 0, @@ -2426,7 +2426,7 @@ "type": "t_address" }, { - "astId": 5706, + "astId": 5721, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "poolsAssetsDirectTransfer", "offset": 0, @@ -2478,7 +2478,7 @@ "label": "contract ResilientOracle", "numberOfBytes": "20" }, - "t_enum(ConversionAccessibility)5455": { + "t_enum(ConversionAccessibility)5470": { "encoding": "inplace", "label": "enum IAbstractTokenConverter.ConversionAccessibility", "numberOfBytes": "1" @@ -2497,12 +2497,12 @@ "numberOfBytes": "32", "value": "t_mapping(t_address,t_bool)" }, - "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5463_storage))": { + "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5478_storage))": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => mapping(address => struct IAbstractTokenConverter.ConversionConfig))", "numberOfBytes": "32", - "value": "t_mapping(t_address,t_struct(ConversionConfig)5463_storage)" + "value": "t_mapping(t_address,t_struct(ConversionConfig)5478_storage)" }, "t_mapping(t_address,t_mapping(t_address,t_uint256))": { "encoding": "mapping", @@ -2511,12 +2511,12 @@ "numberOfBytes": "32", "value": "t_mapping(t_address,t_uint256)" }, - "t_mapping(t_address,t_struct(ConversionConfig)5463_storage)": { + "t_mapping(t_address,t_struct(ConversionConfig)5478_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct IAbstractTokenConverter.ConversionConfig)", "numberOfBytes": "32", - "value": "t_struct(ConversionConfig)5463_storage" + "value": "t_struct(ConversionConfig)5478_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2525,12 +2525,12 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_struct(ConversionConfig)5463_storage": { + "t_struct(ConversionConfig)5478_storage": { "encoding": "inplace", "label": "struct IAbstractTokenConverter.ConversionConfig", "members": [ { - "astId": 5458, + "astId": 5473, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "incentive", "offset": 0, @@ -2538,12 +2538,12 @@ "type": "t_uint256" }, { - "astId": 5462, + "astId": 5477, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "conversionAccess", "offset": 0, "slot": "1", - "type": "t_enum(ConversionAccessibility)5455" + "type": "t_enum(ConversionAccessibility)5470" } ], "numberOfBytes": "64" diff --git a/deployments/bsctestnet/SingleTokenConverterImp.json b/deployments/bsctestnet/SingleTokenConverterImp.json index 5337bd95..1d5aa382 100644 --- a/deployments/bsctestnet/SingleTokenConverterImp.json +++ b/deployments/bsctestnet/SingleTokenConverterImp.json @@ -1,5 +1,5 @@ { - "address": "0xf014C86b6071cfFB8fE39306F802770C70733a23", + "address": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", "abi": [ { "inputs": [], @@ -1381,39 +1381,39 @@ "type": "function" } ], - "transactionHash": "0xcf729c527b28bfdfaba00d98555c4a4d8e62d27dae23532a37fa81ff5fd4ee4c", + "transactionHash": "0xba9a92fb7e9385bbebc2d54c39b4d53d3511b3e443abb0158ab09a03342c6f79", "receipt": { "to": null, - "from": "0x02EB950C215D12d723b44a18CfF098C6E166C531", - "contractAddress": "0xf014C86b6071cfFB8fE39306F802770C70733a23", - "transactionIndex": 4, - "gasUsed": "3623804", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000080000000000000000000000000000000000000000000000400000000000000200000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5aebee3f25eaf1a91eab717c280f51ca89a3d6b272c6fa6e367fde46c7e0c41b", - "transactionHash": "0xcf729c527b28bfdfaba00d98555c4a4d8e62d27dae23532a37fa81ff5fd4ee4c", + "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", + "contractAddress": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", + "transactionIndex": 0, + "gasUsed": "3634796", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000080000000000000000000010000000000000000000000000400000000000000000000000000000000000800000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x446e0df3da06877fbeded838f80f30a728834ebdba83c4fd0140eb7b87ace215", + "transactionHash": "0xba9a92fb7e9385bbebc2d54c39b4d53d3511b3e443abb0158ab09a03342c6f79", "logs": [ { - "transactionIndex": 4, - "blockNumber": 36750636, - "transactionHash": "0xcf729c527b28bfdfaba00d98555c4a4d8e62d27dae23532a37fa81ff5fd4ee4c", - "address": "0xf014C86b6071cfFB8fE39306F802770C70733a23", + "transactionIndex": 0, + "blockNumber": 37698228, + "transactionHash": "0xba9a92fb7e9385bbebc2d54c39b4d53d3511b3e443abb0158ab09a03342c6f79", + "address": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "logIndex": 4, - "blockHash": "0x5aebee3f25eaf1a91eab717c280f51ca89a3d6b272c6fa6e367fde46c7e0c41b" + "logIndex": 0, + "blockHash": "0x446e0df3da06877fbeded838f80f30a728834ebdba83c4fd0140eb7b87ace215" } ], - "blockNumber": 36750636, - "cumulativeGasUsed": "4621429", + "blockNumber": 37698228, + "cumulativeGasUsed": "3634796", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "d02e743d886d63634298edb2c3d7a019", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newBaseAsset\",\"type\":\"address\"}],\"name\":\"BaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"}],\"name\":\"setBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Balance of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256)\":{\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"Minimum amount to convert\",\"priceOracle_\":\"Resilient oracle address\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"baseAsset_\":\"The new address of the base asset\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"SingleTokenConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"BaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when base asset is updated\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"baseAsset()\":{\"notice\":\"Address of the base asset token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setBaseAsset(address)\":{\"notice\":\"Sets the base asset for the contract\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"SingleTokenConverter used for token conversions and sends received tokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/SingleTokenConverter.sol\":\"SingleTokenConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa =\\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\\n tokenInToOutConversion; //round-up\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa =\\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\\n (tokenOutUnderlyingPrice * EXP_SCALE);\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n}\\n\",\"keccak256\":\"0xe10a4505a941511a1e57e162dc5b7d6e4874e40ad421828bc4d6366b51b5608c\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/SingleTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\n\\n/// @title SingleTokenConverter\\n/// @author Venus\\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract SingleTokenConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the base asset token\\n address public baseAsset;\\n\\n /// @notice Emitted when base asset is updated\\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ Minimum amount to convert\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address baseAsset_,\\n uint256 minAmountToConvert_\\n ) public initializer {\\n _setBaseAsset(baseAsset_);\\n\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @notice Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:access Only Governance\\n function setBaseAsset(address baseAsset_) external onlyOwner {\\n _setBaseAsset(baseAsset_);\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n tokenBalance = token.balanceOf(address(this));\\n }\\n\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address.\\n /// @return balanceLeft Amount of asset, for _privateConversion\\n // solhint-disable-next-line\\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 balance = token.balanceOf(address(this));\\n balanceLeft = balance;\\n\\n if (asset == baseAsset) {\\n balanceLeft = 0;\\n token.safeTransfer(destinationAddress, balance);\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\\n }\\n }\\n\\n /// @dev Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n /// @custom:event BaseAssetUpdated is emitted on success\\n function _setBaseAsset(address baseAsset_) internal {\\n ensureNonzeroAddress(baseAsset_);\\n emit BaseAssetUpdated(baseAsset, baseAsset_);\\n baseAsset = baseAsset_;\\n }\\n\\n /// @dev Get base asset address\\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = baseAsset;\\n }\\n}\\n\",\"keccak256\":\"0xde2e9d5ef380a06a222825b11ffa47edad9e7624e3e90b8b55c92562f9216e76\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61408c80620000f36000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d4366004613802565b610562565b005b6102ee6102e936600461381f565b610576565b60408051928352602083019190915201610288565b6102d9610311366004613802565b610624565b60fc54610274906001600160a01b031681565b6102d9610337366004613802565b610635565b6102ee61034a366004613861565b610646565b6102d961035d366004613802565b610784565b6102d9610370366004613802565b610795565b6102d96107a6565b6102ee61038b36600461381f565b61088c565b6102d961039e3660046138c0565b610973565b6102ee6103b136600461381f565b610a10565b6102ee6103c436600461381f565b610b19565b6103dc6103d7366004613802565b610c18565b604051908152602001610288565b6102d9610ca5565b6102d9610400366004613901565b610cb9565b6102d9610d00565b6033546001600160a01b0316610274565b6102ee61042c366004613861565b610d90565b6102d961043f36600461391a565b610e7a565b61047961045236600461391a565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139bd565b6097546001600160a01b0316610274565b6102ee6104a6366004613861565b610eb0565b6102d9610f9a565b6102d96104c1366004613a1d565b61104c565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613861565b6110ea565b6102d961052e366004613ad1565b61120d565b6102d9610541366004613802565b6115ac565b6102d9610554366004613b42565b611635565b6103dc60fb5481565b61056a6117bf565b61057381611819565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b8613953565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610c18565b905085811015610608578095505b859250610616868686611896565b508092505050935093915050565b61062c6117bf565b61057381611bba565b61063d6117bf565b61057381611caf565b600080828585610654611d2e565b61065d83611d83565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611dc3565b6106da8a8a8a8a8a611e1c565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117bf565b61057381611ea3565b61079d6117bf565b61057381611f20565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611f9d565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce613953565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610915868686612069565b9092509050600061092585610c18565b9050828110156109695781600181610945670de0b6b3a764000085613bd5565b61094f9190613c12565b6109599190613c2a565b6109639190613c41565b93508092505b5050935093915050565b61097b6117bf565b610983611dc3565b61098c83611d83565b61099582611d83565b61099e8161238a565b826109b36001600160a01b03821684846123c4565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109f891815260200190565b60405180910390a350610a0b600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b50505050610b0f858585612069565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b7d57600080fd5b505af1158015610b91573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bf557600080fd5b505af1158015610c09573d6000803e3d6000fd5b50505050610b0f858585611896565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9e9190613c7c565b9392505050565b610cad6117bf565b610cb7600061248b565b565b610cf76040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611f9d565b610573816124bc565b60655433906001600160a01b03168114610d875760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6105738161248b565b600080828585610d9e611d2e565b610da783611d83565b816001600160a01b0316836001600160a01b03161480610dd85750806001600160a01b0316836001600160a01b0316145b15610e0f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e17611dc3565b610e248a8a8a8a8a611e1c565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e82611dc3565b6000610e8e8383612506565b90508015610ea157610ea183838361261b565b50610eac600160c955565b5050565b600080828585610ebe611d2e565b610ec783611d83565b816001600160a01b0316836001600160a01b03161480610ef85750806001600160a01b0316836001600160a01b0316145b15610f2f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f37611dc3565b610f448a8a8a8a8a612ad8565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fd86040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611f9d565b610fe0611d2e565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b82818114611086576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110e1576110d9878787848181106110a7576110a7613c95565b90506020020160208101906110bc9190613802565b8686858181106110ce576110ce613c95565b90506040020161120d565b600101611089565b50505050505050565b6000808285856110f8611d2e565b61110183611d83565b816001600160a01b0316836001600160a01b031614806111325750806001600160a01b0316836001600160a01b0316145b15611169576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611171611dc3565b61117e8a8a8a8a8a612b6a565b90955093508884146111bc576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61122e60405180606001604052806035815260200161402260359139611f9d565b61123783611d83565b61124082611d83565b6706f05b59d3b2000081351115611294576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d7e565b816001600160a01b0316836001600160a01b031614806112c3575061012d546001600160a01b03848116911614155b8061130b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561130857611308613953565b14155b15611342576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113546040830160208401613cc4565b600381111561136557611365613953565b1480156113725750803515155b156113a9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113bb6040830160208401613cc4565b60038111156113cc576113cc613953565b14806113f8575060016113e56040830160208401613cc4565b60038111156113f6576113f6613953565b145b801561140d575060ff546001600160a01b0316155b15611444576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff909116916114b491908a01908a01613cc4565b6040516114c49493929190613ce5565b60405180910390a360006114de6040840160208501613cc4565b60038111156114ef576114ef613953565b0361154c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556115a6565b813581556115606040830160208401613cc4565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115a0576115a0613953565b02179055505b50505050565b6115b46117bf565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115fd6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff16158080156116555750600054600160ff909116105b8061166f5750303b15801561166f575060005460ff166001145b6116e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d7e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561173f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61174883611caf565b61175486868685612c27565b80156117b757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610cb75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d7e565b61182281611d83565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118d3576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561192757611927613953565b600381111561193857611938613953565b905250905060008160200151600381111561195557611955613953565b0361198c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a149190613c7c565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613c7c565b835160ff54919250906001600160a01b031615801590611b41575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b419190613d16565b15611b4a575060005b6000611b5e82670de0b6b3a7640000613c12565b905082611b6b8286613bd5565b611b759190613c41565b955085600181611b8d670de0b6b3a76400008e613bd5565b611b979190613c12565b611ba19190613c2a565b611bab9190613c41565b96505050505050935093915050565b6001600160a01b038116611c365760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d7e565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611cb881611d83565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610cb7576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e155760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d7e565b600260c955565b600080611e298585612cc0565b611e338588612de0565b9150611e40828686610a10565b91505085811015611e87576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d7e565b611e92848483612f2b565b9550959350505050565b600160c955565b611eac81611d83565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f2981611d83565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab90611fe99033908690600401613dae565b602060405180830381865afa158015612006573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202a9190613d16565b905080610eac573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d7e93929190613dd0565b600080846000036120a6576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff1660038111156120fa576120fa613953565b600381111561210b5761210b613953565b905250905060008160200151600381111561212857612128613953565b0361215f576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e79190613c7c565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612250573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122749190613c7c565b835160ff54919250906001600160a01b031615801590612314575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa1580156122f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123149190613d16565b1561231d575060005b600061233182670de0b6b3a7640000613c12565b9050612345670de0b6b3a764000084613bd5565b81612350868d613bd5565b61235a9190613bd5565b6123649190613c41565b9650826123718286613bd5565b61237b9190613c41565b95505050505050935093915050565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610a0b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612f8e565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561057381613076565b6124c58161238a565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa15801561256a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258e9190613c7c565b61012d549093508391506001600160a01b03908116908516036126135760fe54600093506125c9906001600160a01b038481169116836123c4565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061263061012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612ad35760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126bf573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526127059190810190613f09565b8151919350915060005b81811015612ace5782818151811061272957612729613c95565b602002602001015160000315612ace57600084828151811061274d5761274d613c95565b60200260200101516001600160a01b0316636f1a30a885848151811061277557612775613c95565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127b7939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af11580156127d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f99190613fce565b915050888111156128075750875b612811818b6130e0565b61281b5750612ace565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613c7c565b90508a6001600160a01b031663095ea7b38785815181106128c5576128c5613c95565b6020026020010151846040518363ffffffff1660e01b81526004016128ff9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af115801561291e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129429190613d16565b5085838151811061295557612955613c95565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af11580156129df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a039190613fce565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c9190613c7c565b9050612a98838c613c2a565b9a50612aa48282613c2a565b612aae9089613c12565b97508a600003612ac057505050612ace565b83600101935050505061270f565b505050505b6117b7565b600080612ae58585612cc0565b6000612af2878787610b19565b91505087811115612b39576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612b438682612de0565b9250612b50838787610a10565b9250612b5f9050858584612f2b565b509550959350505050565b600080612b778585612cc0565b6000612b84878787610b19565b915050612b918682612de0565b9250808314612bcc576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c10576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612c1b858589612f2b565b50909694955050505050565b600054610100900460ff16612ca45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b612cad84613218565b612cb56132a6565b6115a683838361332b565b60ff546000906001600160a01b031615801590612d5d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5d9190613d16565b905080158015612da9575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612da757612da7613953565b145b15610a0b576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6d9190613c7c565b60fe54909150612e8c906001600160a01b0384811691339116876133f0565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f159190613c7c565b9050612f218282613c2a565b9695505050505050565b6000612f3684610c18565b905081811015612f72576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612f876001600160a01b03821685856123c4565b5050505050565b6000612fe3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134419092919063ffffffff16565b90508051600014806130045750808060200190518101906130049190613d16565b610a0b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d7e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561314157600080fd5b505af1158015613155573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156131c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ed9190613c7c565b6131f79190613bd5565b6132019190613c41565b905060fb54811061321157600191505b5092915050565b600054610100900460ff166132955760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b61329d613458565b610573816134dd565b600054610100900460ff166133235760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb761355a565b600054610100900460ff166133a85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6133b183611f20565b6133ba82611819565b6133c3816124bc565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b03808516602483015283166044820152606481018290526115a69085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612409565b606061345084846000856135d7565b949350505050565b600054610100900460ff166134d55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb76136c9565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b600054610100900460ff16611e9c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b60608247101561364f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d7e565b600080866001600160a01b0316858760405161366b9190613ff2565b60006040518083038185875af1925050503d80600081146136a8576040519150601f19603f3d011682016040523d82523d6000602084013e6136ad565b606091505b50915091506136be8783838761374f565b979650505050505050565b600054610100900460ff166137465760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb73361248b565b606083156137be5782516000036137b7576001600160a01b0385163b6137b75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d7e565b5081613450565b61345083838151156137d35781518083602001fd5b8060405162461bcd60e51b8152600401610d7e919061400e565b6001600160a01b038116811461057357600080fd5b60006020828403121561381457600080fd5b8135610c9e816137ed565b60008060006060848603121561383457600080fd5b833592506020840135613846816137ed565b91506040840135613856816137ed565b809150509250925092565b600080600080600060a0868803121561387957600080fd5b85359450602086013593506040860135613892816137ed565b925060608601356138a2816137ed565b915060808601356138b2816137ed565b809150509295509295909350565b6000806000606084860312156138d557600080fd5b83356138e0816137ed565b925060208401356138f0816137ed565b929592945050506040919091013590565b60006020828403121561391357600080fd5b5035919050565b6000806040838503121561392d57600080fd5b8235613938816137ed565b91506020830135613948816137ed565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139b9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c9e6020830184613982565b60008083601f8401126139e357600080fd5b50813567ffffffffffffffff8111156139fb57600080fd5b6020830191508360208260061b8501011115613a1657600080fd5b9250929050565b600080600080600060608688031215613a3557600080fd5b8535613a40816137ed565b9450602086013567ffffffffffffffff80821115613a5d57600080fd5b818801915088601f830112613a7157600080fd5b813581811115613a8057600080fd5b8960208260051b8501011115613a9557600080fd5b602083019650809550506040880135915080821115613ab357600080fd5b50613ac0888289016139d1565b969995985093965092949392505050565b60008060008385036080811215613ae757600080fd5b8435613af2816137ed565b93506020850135613b02816137ed565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b3457600080fd5b506040840190509250925092565b600080600080600060a08688031215613b5a57600080fd5b8535613b65816137ed565b94506020860135613b75816137ed565b93506040860135613b85816137ed565b92506060860135613b95816137ed565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c0d57613c0d613ba6565b500290565b60008219821115613c2557613c25613ba6565b500190565b600082821015613c3c57613c3c613ba6565b500390565b600082613c77577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613c8e57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613cd657600080fd5b813560048110610c9e57600080fd5b8481526020810184905260808101613d006040830185613982565b613d0d6060830184613982565b95945050505050565b600060208284031215613d2857600080fd5b81518015158114610c9e57600080fd5b60005b83811015613d53578181015183820152602001613d3b565b838111156115a65750506000910152565b60008151808452613d7c816020860160208601613d38565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134506040830184613d64565b60006001600160a01b03808616835280851660208401525060606040830152613d0d6060830184613d64565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613e7257613e72613dfc565b604052919050565b600067ffffffffffffffff821115613e9457613e94613dfc565b5060051b60200190565b600082601f830112613eaf57600080fd5b81516020613ec4613ebf83613e7a565b613e2b565b82815260059290921b84018101918181019086841115613ee357600080fd5b8286015b84811015613efe5780518352918301918301613ee7565b509695505050505050565b60008060408385031215613f1c57600080fd5b825167ffffffffffffffff80821115613f3457600080fd5b818501915085601f830112613f4857600080fd5b81516020613f58613ebf83613e7a565b82815260059290921b84018101918181019089841115613f7757600080fd5b948201945b83861015613f9e578551613f8f816137ed565b82529482019490820190613f7c565b91880151919650909350505080821115613fb757600080fd5b50613fc485828601613e9e565b9150509250929050565b60008060408385031215613fe157600080fd5b505080516020909101519092909150565b60008251614004818460208701613d38565b9190910192915050565b602081526000610c9e6020830184613d6456fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220fbd82e06735677bc9d44b30a618a4cd1179b2083744b3d0aafc0351f632f937464736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d4366004613802565b610562565b005b6102ee6102e936600461381f565b610576565b60408051928352602083019190915201610288565b6102d9610311366004613802565b610624565b60fc54610274906001600160a01b031681565b6102d9610337366004613802565b610635565b6102ee61034a366004613861565b610646565b6102d961035d366004613802565b610784565b6102d9610370366004613802565b610795565b6102d96107a6565b6102ee61038b36600461381f565b61088c565b6102d961039e3660046138c0565b610973565b6102ee6103b136600461381f565b610a10565b6102ee6103c436600461381f565b610b19565b6103dc6103d7366004613802565b610c18565b604051908152602001610288565b6102d9610ca5565b6102d9610400366004613901565b610cb9565b6102d9610d00565b6033546001600160a01b0316610274565b6102ee61042c366004613861565b610d90565b6102d961043f36600461391a565b610e7a565b61047961045236600461391a565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139bd565b6097546001600160a01b0316610274565b6102ee6104a6366004613861565b610eb0565b6102d9610f9a565b6102d96104c1366004613a1d565b61104c565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613861565b6110ea565b6102d961052e366004613ad1565b61120d565b6102d9610541366004613802565b6115ac565b6102d9610554366004613b42565b611635565b6103dc60fb5481565b61056a6117bf565b61057381611819565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b8613953565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610c18565b905085811015610608578095505b859250610616868686611896565b508092505050935093915050565b61062c6117bf565b61057381611bba565b61063d6117bf565b61057381611caf565b600080828585610654611d2e565b61065d83611d83565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611dc3565b6106da8a8a8a8a8a611e1c565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117bf565b61057381611ea3565b61079d6117bf565b61057381611f20565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611f9d565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce613953565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610915868686612069565b9092509050600061092585610c18565b9050828110156109695781600181610945670de0b6b3a764000085613bd5565b61094f9190613c12565b6109599190613c2a565b6109639190613c41565b93508092505b5050935093915050565b61097b6117bf565b610983611dc3565b61098c83611d83565b61099582611d83565b61099e8161238a565b826109b36001600160a01b03821684846123c4565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109f891815260200190565b60405180910390a350610a0b600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b50505050610b0f858585612069565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b7d57600080fd5b505af1158015610b91573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bf557600080fd5b505af1158015610c09573d6000803e3d6000fd5b50505050610b0f858585611896565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9e9190613c7c565b9392505050565b610cad6117bf565b610cb7600061248b565b565b610cf76040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611f9d565b610573816124bc565b60655433906001600160a01b03168114610d875760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6105738161248b565b600080828585610d9e611d2e565b610da783611d83565b816001600160a01b0316836001600160a01b03161480610dd85750806001600160a01b0316836001600160a01b0316145b15610e0f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e17611dc3565b610e248a8a8a8a8a611e1c565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e82611dc3565b6000610e8e8383612506565b90508015610ea157610ea183838361261b565b50610eac600160c955565b5050565b600080828585610ebe611d2e565b610ec783611d83565b816001600160a01b0316836001600160a01b03161480610ef85750806001600160a01b0316836001600160a01b0316145b15610f2f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f37611dc3565b610f448a8a8a8a8a612ad8565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fd86040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611f9d565b610fe0611d2e565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b82818114611086576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110e1576110d9878787848181106110a7576110a7613c95565b90506020020160208101906110bc9190613802565b8686858181106110ce576110ce613c95565b90506040020161120d565b600101611089565b50505050505050565b6000808285856110f8611d2e565b61110183611d83565b816001600160a01b0316836001600160a01b031614806111325750806001600160a01b0316836001600160a01b0316145b15611169576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611171611dc3565b61117e8a8a8a8a8a612b6a565b90955093508884146111bc576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61122e60405180606001604052806035815260200161402260359139611f9d565b61123783611d83565b61124082611d83565b6706f05b59d3b2000081351115611294576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d7e565b816001600160a01b0316836001600160a01b031614806112c3575061012d546001600160a01b03848116911614155b8061130b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561130857611308613953565b14155b15611342576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113546040830160208401613cc4565b600381111561136557611365613953565b1480156113725750803515155b156113a9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113bb6040830160208401613cc4565b60038111156113cc576113cc613953565b14806113f8575060016113e56040830160208401613cc4565b60038111156113f6576113f6613953565b145b801561140d575060ff546001600160a01b0316155b15611444576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff909116916114b491908a01908a01613cc4565b6040516114c49493929190613ce5565b60405180910390a360006114de6040840160208501613cc4565b60038111156114ef576114ef613953565b0361154c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556115a6565b813581556115606040830160208401613cc4565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115a0576115a0613953565b02179055505b50505050565b6115b46117bf565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115fd6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff16158080156116555750600054600160ff909116105b8061166f5750303b15801561166f575060005460ff166001145b6116e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d7e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561173f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61174883611caf565b61175486868685612c27565b80156117b757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610cb75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d7e565b61182281611d83565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118d3576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561192757611927613953565b600381111561193857611938613953565b905250905060008160200151600381111561195557611955613953565b0361198c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a149190613c7c565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613c7c565b835160ff54919250906001600160a01b031615801590611b41575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b419190613d16565b15611b4a575060005b6000611b5e82670de0b6b3a7640000613c12565b905082611b6b8286613bd5565b611b759190613c41565b955085600181611b8d670de0b6b3a76400008e613bd5565b611b979190613c12565b611ba19190613c2a565b611bab9190613c41565b96505050505050935093915050565b6001600160a01b038116611c365760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d7e565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611cb881611d83565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610cb7576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e155760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d7e565b600260c955565b600080611e298585612cc0565b611e338588612de0565b9150611e40828686610a10565b91505085811015611e87576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d7e565b611e92848483612f2b565b9550959350505050565b600160c955565b611eac81611d83565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f2981611d83565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab90611fe99033908690600401613dae565b602060405180830381865afa158015612006573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202a9190613d16565b905080610eac573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d7e93929190613dd0565b600080846000036120a6576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff1660038111156120fa576120fa613953565b600381111561210b5761210b613953565b905250905060008160200151600381111561212857612128613953565b0361215f576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e79190613c7c565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612250573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122749190613c7c565b835160ff54919250906001600160a01b031615801590612314575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa1580156122f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123149190613d16565b1561231d575060005b600061233182670de0b6b3a7640000613c12565b9050612345670de0b6b3a764000084613bd5565b81612350868d613bd5565b61235a9190613bd5565b6123649190613c41565b9650826123718286613bd5565b61237b9190613c41565b95505050505050935093915050565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610a0b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612f8e565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561057381613076565b6124c58161238a565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa15801561256a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258e9190613c7c565b61012d549093508391506001600160a01b03908116908516036126135760fe54600093506125c9906001600160a01b038481169116836123c4565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061263061012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612ad35760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126bf573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526127059190810190613f09565b8151919350915060005b81811015612ace5782818151811061272957612729613c95565b602002602001015160000315612ace57600084828151811061274d5761274d613c95565b60200260200101516001600160a01b0316636f1a30a885848151811061277557612775613c95565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127b7939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af11580156127d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f99190613fce565b915050888111156128075750875b612811818b6130e0565b61281b5750612ace565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613c7c565b90508a6001600160a01b031663095ea7b38785815181106128c5576128c5613c95565b6020026020010151846040518363ffffffff1660e01b81526004016128ff9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af115801561291e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129429190613d16565b5085838151811061295557612955613c95565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af11580156129df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a039190613fce565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c9190613c7c565b9050612a98838c613c2a565b9a50612aa48282613c2a565b612aae9089613c12565b97508a600003612ac057505050612ace565b83600101935050505061270f565b505050505b6117b7565b600080612ae58585612cc0565b6000612af2878787610b19565b91505087811115612b39576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612b438682612de0565b9250612b50838787610a10565b9250612b5f9050858584612f2b565b509550959350505050565b600080612b778585612cc0565b6000612b84878787610b19565b915050612b918682612de0565b9250808314612bcc576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c10576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612c1b858589612f2b565b50909694955050505050565b600054610100900460ff16612ca45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b612cad84613218565b612cb56132a6565b6115a683838361332b565b60ff546000906001600160a01b031615801590612d5d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5d9190613d16565b905080158015612da9575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612da757612da7613953565b145b15610a0b576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6d9190613c7c565b60fe54909150612e8c906001600160a01b0384811691339116876133f0565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f159190613c7c565b9050612f218282613c2a565b9695505050505050565b6000612f3684610c18565b905081811015612f72576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612f876001600160a01b03821685856123c4565b5050505050565b6000612fe3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134419092919063ffffffff16565b90508051600014806130045750808060200190518101906130049190613d16565b610a0b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d7e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561314157600080fd5b505af1158015613155573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156131c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ed9190613c7c565b6131f79190613bd5565b6132019190613c41565b905060fb54811061321157600191505b5092915050565b600054610100900460ff166132955760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b61329d613458565b610573816134dd565b600054610100900460ff166133235760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb761355a565b600054610100900460ff166133a85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6133b183611f20565b6133ba82611819565b6133c3816124bc565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b03808516602483015283166044820152606481018290526115a69085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612409565b606061345084846000856135d7565b949350505050565b600054610100900460ff166134d55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb76136c9565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b600054610100900460ff16611e9c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b60608247101561364f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d7e565b600080866001600160a01b0316858760405161366b9190613ff2565b60006040518083038185875af1925050503d80600081146136a8576040519150601f19603f3d011682016040523d82523d6000602084013e6136ad565b606091505b50915091506136be8783838761374f565b979650505050505050565b600054610100900460ff166137465760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb73361248b565b606083156137be5782516000036137b7576001600160a01b0385163b6137b75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d7e565b5081613450565b61345083838151156137d35781518083602001fd5b8060405162461bcd60e51b8152600401610d7e919061400e565b6001600160a01b038116811461057357600080fd5b60006020828403121561381457600080fd5b8135610c9e816137ed565b60008060006060848603121561383457600080fd5b833592506020840135613846816137ed565b91506040840135613856816137ed565b809150509250925092565b600080600080600060a0868803121561387957600080fd5b85359450602086013593506040860135613892816137ed565b925060608601356138a2816137ed565b915060808601356138b2816137ed565b809150509295509295909350565b6000806000606084860312156138d557600080fd5b83356138e0816137ed565b925060208401356138f0816137ed565b929592945050506040919091013590565b60006020828403121561391357600080fd5b5035919050565b6000806040838503121561392d57600080fd5b8235613938816137ed565b91506020830135613948816137ed565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139b9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c9e6020830184613982565b60008083601f8401126139e357600080fd5b50813567ffffffffffffffff8111156139fb57600080fd5b6020830191508360208260061b8501011115613a1657600080fd5b9250929050565b600080600080600060608688031215613a3557600080fd5b8535613a40816137ed565b9450602086013567ffffffffffffffff80821115613a5d57600080fd5b818801915088601f830112613a7157600080fd5b813581811115613a8057600080fd5b8960208260051b8501011115613a9557600080fd5b602083019650809550506040880135915080821115613ab357600080fd5b50613ac0888289016139d1565b969995985093965092949392505050565b60008060008385036080811215613ae757600080fd5b8435613af2816137ed565b93506020850135613b02816137ed565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b3457600080fd5b506040840190509250925092565b600080600080600060a08688031215613b5a57600080fd5b8535613b65816137ed565b94506020860135613b75816137ed565b93506040860135613b85816137ed565b92506060860135613b95816137ed565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c0d57613c0d613ba6565b500290565b60008219821115613c2557613c25613ba6565b500190565b600082821015613c3c57613c3c613ba6565b500390565b600082613c77577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613c8e57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613cd657600080fd5b813560048110610c9e57600080fd5b8481526020810184905260808101613d006040830185613982565b613d0d6060830184613982565b95945050505050565b600060208284031215613d2857600080fd5b81518015158114610c9e57600080fd5b60005b83811015613d53578181015183820152602001613d3b565b838111156115a65750506000910152565b60008151808452613d7c816020860160208601613d38565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134506040830184613d64565b60006001600160a01b03808616835280851660208401525060606040830152613d0d6060830184613d64565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613e7257613e72613dfc565b604052919050565b600067ffffffffffffffff821115613e9457613e94613dfc565b5060051b60200190565b600082601f830112613eaf57600080fd5b81516020613ec4613ebf83613e7a565b613e2b565b82815260059290921b84018101918181019086841115613ee357600080fd5b8286015b84811015613efe5780518352918301918301613ee7565b509695505050505050565b60008060408385031215613f1c57600080fd5b825167ffffffffffffffff80821115613f3457600080fd5b818501915085601f830112613f4857600080fd5b81516020613f58613ebf83613e7a565b82815260059290921b84018101918181019089841115613f7757600080fd5b948201945b83861015613f9e578551613f8f816137ed565b82529482019490820190613f7c565b91880151919650909350505080821115613fb757600080fd5b50613fc485828601613e9e565b9150509250929050565b60008060408385031215613fe157600080fd5b505080516020909101519092909150565b60008251614004818460208701613d38565b9190910192915050565b602081526000610c9e6020830184613d6456fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220fbd82e06735677bc9d44b30a618a4cd1179b2083744b3d0aafc0351f632f937464736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "e9f683aad829bf9574e4eef6b067ab3e", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newBaseAsset\",\"type\":\"address\"}],\"name\":\"BaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"}],\"name\":\"setBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Balance of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256)\":{\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"baseAsset_\":\"Address of the base asset\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"Minimum amount to convert\",\"priceOracle_\":\"Resilient oracle address\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"baseAsset_\":\"The new address of the base asset\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"SingleTokenConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"BaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when base asset is updated\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"baseAsset()\":{\"notice\":\"Address of the base asset token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setBaseAsset(address)\":{\"notice\":\"Sets the base asset for the contract\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"SingleTokenConverter used for token conversions and sends received tokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/SingleTokenConverter.sol\":\"SingleTokenConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa =\\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\\n tokenInToOutConversion; //round-up\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa =\\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\\n (tokenOutUnderlyingPrice * EXP_SCALE);\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n\\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\\n converterNetwork.isTokenConverter(msg.sender);\\n if (isPrivateConversion) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n if (isPrivateConversion) {\\n amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion;\\n } else {\\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\\n }\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n}\\n\",\"keccak256\":\"0xdecdaf378a5af7744557fc29495d6db49c6900be1b03bcb6faa2b3a23c9a5c59\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/SingleTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\n\\n/// @title SingleTokenConverter\\n/// @author Venus\\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract SingleTokenConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the base asset token\\n address public baseAsset;\\n\\n /// @notice Emitted when base asset is updated\\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param baseAsset_ Address of the base asset\\n /// @param minAmountToConvert_ Minimum amount to convert\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address baseAsset_,\\n uint256 minAmountToConvert_\\n ) public initializer {\\n _setBaseAsset(baseAsset_);\\n\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @notice Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:access Only Governance\\n function setBaseAsset(address baseAsset_) external onlyOwner {\\n _setBaseAsset(baseAsset_);\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n tokenBalance = token.balanceOf(address(this));\\n }\\n\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address.\\n /// @return balanceLeft Amount of asset, for _privateConversion\\n // solhint-disable-next-line\\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 balance = token.balanceOf(address(this));\\n balanceLeft = balance;\\n\\n if (asset == baseAsset) {\\n balanceLeft = 0;\\n token.safeTransfer(destinationAddress, balance);\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\\n }\\n }\\n\\n /// @dev Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n /// @custom:event BaseAssetUpdated is emitted on success\\n function _setBaseAsset(address baseAsset_) internal {\\n ensureNonzeroAddress(baseAsset_);\\n emit BaseAssetUpdated(baseAsset, baseAsset_);\\n baseAsset = baseAsset_;\\n }\\n\\n /// @dev Get base asset address\\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = baseAsset;\\n }\\n}\\n\",\"keccak256\":\"0x385804c4f8a1d5b0ed58da01f584c778e2a869b280ad6cb607b7fe8539c51897\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6140bf80620000f36000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d4366004613835565b610562565b005b6102ee6102e9366004613852565b610576565b60408051928352602083019190915201610288565b6102d9610311366004613835565b610624565b60fc54610274906001600160a01b031681565b6102d9610337366004613835565b610635565b6102ee61034a366004613894565b610646565b6102d961035d366004613835565b610784565b6102d9610370366004613835565b610795565b6102d96107a6565b6102ee61038b366004613852565b61088c565b6102d961039e3660046138f3565b610973565b6102ee6103b1366004613852565b610a10565b6102ee6103c4366004613852565b610b19565b6103dc6103d7366004613835565b610c18565b604051908152602001610288565b6102d9610ca5565b6102d9610400366004613934565b610cb9565b6102d9610d00565b6033546001600160a01b0316610274565b6102ee61042c366004613894565b610d90565b6102d961043f36600461394d565b610e7a565b61047961045236600461394d565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139f0565b6097546001600160a01b0316610274565b6102ee6104a6366004613894565b610eb0565b6102d9610f9a565b6102d96104c1366004613a50565b61104c565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613894565b6110ea565b6102d961052e366004613b04565b61120d565b6102d9610541366004613835565b6115ac565b6102d9610554366004613b75565b611635565b6103dc60fb5481565b61056a6117bf565b61057381611819565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b8613986565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610c18565b905085811015610608578095505b859250610616868686611896565b508092505050935093915050565b61062c6117bf565b61057381611bed565b61063d6117bf565b61057381611ce2565b600080828585610654611d61565b61065d83611db6565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611df6565b6106da8a8a8a8a8a611e4f565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117bf565b61057381611ed6565b61079d6117bf565b61057381611f53565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611fd0565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce613986565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b849150600061091586868661209c565b9092509050600061092585610c18565b9050828110156109695781600181610945670de0b6b3a764000085613c08565b61094f9190613c45565b6109599190613c5d565b6109639190613c74565b93508092505b5050935093915050565b61097b6117bf565b610983611df6565b61098c83611db6565b61099582611db6565b61099e816123bd565b826109b36001600160a01b03821684846123f7565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109f891815260200190565b60405180910390a350610a0b600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b50505050610b0f85858561209c565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b7d57600080fd5b505af1158015610b91573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bf557600080fd5b505af1158015610c09573d6000803e3d6000fd5b50505050610b0f858585611896565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9e9190613caf565b9392505050565b610cad6117bf565b610cb760006124be565b565b610cf76040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611fd0565b610573816124ef565b60655433906001600160a01b03168114610d875760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610573816124be565b600080828585610d9e611d61565b610da783611db6565b816001600160a01b0316836001600160a01b03161480610dd85750806001600160a01b0316836001600160a01b0316145b15610e0f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e17611df6565b610e248a8a8a8a8a611e4f565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e82611df6565b6000610e8e8383612539565b90508015610ea157610ea183838361264e565b50610eac600160c955565b5050565b600080828585610ebe611d61565b610ec783611db6565b816001600160a01b0316836001600160a01b03161480610ef85750806001600160a01b0316836001600160a01b0316145b15610f2f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f37611df6565b610f448a8a8a8a8a612b0b565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fd86040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611fd0565b610fe0611d61565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b82818114611086576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110e1576110d9878787848181106110a7576110a7613cc8565b90506020020160208101906110bc9190613835565b8686858181106110ce576110ce613cc8565b90506040020161120d565b600101611089565b50505050505050565b6000808285856110f8611d61565b61110183611db6565b816001600160a01b0316836001600160a01b031614806111325750806001600160a01b0316836001600160a01b0316145b15611169576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611171611df6565b61117e8a8a8a8a8a612b9d565b90955093508884146111bc576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61122e60405180606001604052806035815260200161405560359139611fd0565b61123783611db6565b61124082611db6565b6706f05b59d3b2000081351115611294576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d7e565b816001600160a01b0316836001600160a01b031614806112c3575061012d546001600160a01b03848116911614155b8061130b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561130857611308613986565b14155b15611342576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113546040830160208401613cf7565b600381111561136557611365613986565b1480156113725750803515155b156113a9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113bb6040830160208401613cf7565b60038111156113cc576113cc613986565b14806113f8575060016113e56040830160208401613cf7565b60038111156113f6576113f6613986565b145b801561140d575060ff546001600160a01b0316155b15611444576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff909116916114b491908a01908a01613cf7565b6040516114c49493929190613d18565b60405180910390a360006114de6040840160208501613cf7565b60038111156114ef576114ef613986565b0361154c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556115a6565b813581556115606040830160208401613cf7565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115a0576115a0613986565b02179055505b50505050565b6115b46117bf565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115fd6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff16158080156116555750600054600160ff909116105b8061166f5750303b15801561166f575060005460ff166001145b6116e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d7e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561173f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61174883611ce2565b61175486868685612c5a565b80156117b757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610cb75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d7e565b61182281611db6565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118d3576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561192757611927613986565b600381111561193857611938613986565b905250905060008160200151600381111561195557611955613986565b0361198c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a149190613caf565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613caf565b835160ff54919250906000906001600160a01b031615801590611b44575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b449190613d49565b90508015611b5157600091505b6000611b6583670de0b6b3a7640000613c45565b905083611b728287613c08565b611b7c9190613c74565b96508115611ba85786611b97670de0b6b3a76400008d613c08565b611ba19190613c74565b9750611bdf565b86600181611bbe670de0b6b3a76400008f613c08565b611bc89190613c45565b611bd29190613c5d565b611bdc9190613c74565b97505b505050505050935093915050565b6001600160a01b038116611c695760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d7e565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611ceb81611db6565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610cb7576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e485760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d7e565b600260c955565b600080611e5c8585612cf3565b611e668588612e13565b9150611e73828686610a10565b91505085811015611eba576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d7e565b611ec5848483612f5e565b9550959350505050565b600160c955565b611edf81611db6565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f5c81611db6565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab9061201c9033908690600401613de1565b602060405180830381865afa158015612039573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061205d9190613d49565b905080610eac573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d7e93929190613e03565b600080846000036120d9576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561212d5761212d613986565b600381111561213e5761213e613986565b905250905060008160200151600381111561215b5761215b613986565b03612192576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221a9190613caf565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612283573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a79190613caf565b835160ff54919250906001600160a01b031615801590612347575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612323573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123479190613d49565b15612350575060005b600061236482670de0b6b3a7640000613c45565b9050612378670de0b6b3a764000084613c08565b81612383868d613c08565b61238d9190613c08565b6123979190613c74565b9650826123a48286613c08565b6123ae9190613c74565b95505050505050935093915050565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610a0b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612fc1565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610573816130a9565b6124f8816123bd565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c19190613caf565b61012d549093508391506001600160a01b03908116908516036126465760fe54600093506125fc906001600160a01b038481169116836123f7565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061266361012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612b065760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126f2573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526127389190810190613f3c565b8151919350915060005b81811015612b015782818151811061275c5761275c613cc8565b602002602001015160000315612b0157600084828151811061278057612780613cc8565b60200260200101516001600160a01b0316636f1a30a88584815181106127a8576127a8613cc8565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127ea939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015612808573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282c9190614001565b9150508881111561283a5750875b612844818b613113565b61284e5750612b01565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa1580156128b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d59190613caf565b90508a6001600160a01b031663095ea7b38785815181106128f8576128f8613cc8565b6020026020010151846040518363ffffffff1660e01b81526004016129329291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015612951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129759190613d49565b5085838151811061298857612988613cc8565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015612a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a369190614001565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abf9190613caf565b9050612acb838c613c5d565b9a50612ad78282613c5d565b612ae19089613c45565b97508a600003612af357505050612b01565b836001019350505050612742565b505050505b6117b7565b600080612b188585612cf3565b6000612b25878787610b19565b91505087811115612b6c576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612b768682612e13565b9250612b83838787610a10565b9250612b929050858584612f5e565b509550959350505050565b600080612baa8585612cf3565b6000612bb7878787610b19565b915050612bc48682612e13565b9250808314612bff576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c43576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612c4e858589612f5e565b50909694955050505050565b600054610100900460ff16612cd75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b612ce08461324b565b612ce86132d9565b6115a683838361335e565b60ff546000906001600160a01b031615801590612d90575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d909190613d49565b905080158015612ddc575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612dda57612dda613986565b145b15610a0b576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea09190613caf565b60fe54909150612ebf906001600160a01b038481169133911687613423565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f489190613caf565b9050612f548282613c5d565b9695505050505050565b6000612f6984610c18565b905081811015612fa5576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612fba6001600160a01b03821685856123f7565b5050505050565b6000613016826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134749092919063ffffffff16565b90508051600014806130375750808060200190518101906130379190613d49565b610a0b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d7e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561317457600080fd5b505af1158015613188573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156131fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132209190613caf565b61322a9190613c08565b6132349190613c74565b905060fb54811061324457600191505b5092915050565b600054610100900460ff166132c85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6132d061348b565b61057381613510565b600054610100900460ff166133565760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb761358d565b600054610100900460ff166133db5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6133e483611f53565b6133ed82611819565b6133f6816124ef565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b03808516602483015283166044820152606481018290526115a69085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161243c565b6060613483848460008561360a565b949350505050565b600054610100900460ff166135085760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb76136fc565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b600054610100900460ff16611ecf5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6060824710156136825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d7e565b600080866001600160a01b0316858760405161369e9190614025565b60006040518083038185875af1925050503d80600081146136db576040519150601f19603f3d011682016040523d82523d6000602084013e6136e0565b606091505b50915091506136f187838387613782565b979650505050505050565b600054610100900460ff166137795760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb7336124be565b606083156137f15782516000036137ea576001600160a01b0385163b6137ea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d7e565b5081613483565b61348383838151156138065781518083602001fd5b8060405162461bcd60e51b8152600401610d7e9190614041565b6001600160a01b038116811461057357600080fd5b60006020828403121561384757600080fd5b8135610c9e81613820565b60008060006060848603121561386757600080fd5b83359250602084013561387981613820565b9150604084013561388981613820565b809150509250925092565b600080600080600060a086880312156138ac57600080fd5b853594506020860135935060408601356138c581613820565b925060608601356138d581613820565b915060808601356138e581613820565b809150509295509295909350565b60008060006060848603121561390857600080fd5b833561391381613820565b9250602084013561392381613820565b929592945050506040919091013590565b60006020828403121561394657600080fd5b5035919050565b6000806040838503121561396057600080fd5b823561396b81613820565b9150602083013561397b81613820565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c9e60208301846139b5565b60008083601f840112613a1657600080fd5b50813567ffffffffffffffff811115613a2e57600080fd5b6020830191508360208260061b8501011115613a4957600080fd5b9250929050565b600080600080600060608688031215613a6857600080fd5b8535613a7381613820565b9450602086013567ffffffffffffffff80821115613a9057600080fd5b818801915088601f830112613aa457600080fd5b813581811115613ab357600080fd5b8960208260051b8501011115613ac857600080fd5b602083019650809550506040880135915080821115613ae657600080fd5b50613af388828901613a04565b969995985093965092949392505050565b60008060008385036080811215613b1a57600080fd5b8435613b2581613820565b93506020850135613b3581613820565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b6757600080fd5b506040840190509250925092565b600080600080600060a08688031215613b8d57600080fd5b8535613b9881613820565b94506020860135613ba881613820565b93506040860135613bb881613820565b92506060860135613bc881613820565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c4057613c40613bd9565b500290565b60008219821115613c5857613c58613bd9565b500190565b600082821015613c6f57613c6f613bd9565b500390565b600082613caa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613cc157600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613d0957600080fd5b813560048110610c9e57600080fd5b8481526020810184905260808101613d3360408301856139b5565b613d4060608301846139b5565b95945050505050565b600060208284031215613d5b57600080fd5b81518015158114610c9e57600080fd5b60005b83811015613d86578181015183820152602001613d6e565b838111156115a65750506000910152565b60008151808452613daf816020860160208601613d6b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134836040830184613d97565b60006001600160a01b03808616835280851660208401525060606040830152613d406060830184613d97565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613ea557613ea5613e2f565b604052919050565b600067ffffffffffffffff821115613ec757613ec7613e2f565b5060051b60200190565b600082601f830112613ee257600080fd5b81516020613ef7613ef283613ead565b613e5e565b82815260059290921b84018101918181019086841115613f1657600080fd5b8286015b84811015613f315780518352918301918301613f1a565b509695505050505050565b60008060408385031215613f4f57600080fd5b825167ffffffffffffffff80821115613f6757600080fd5b818501915085601f830112613f7b57600080fd5b81516020613f8b613ef283613ead565b82815260059290921b84018101918181019089841115613faa57600080fd5b948201945b83861015613fd1578551613fc281613820565b82529482019490820190613faf565b91880151919650909350505080821115613fea57600080fd5b50613ff785828601613ed1565b9150509250929050565b6000806040838503121561401457600080fd5b505080516020909101519092909150565b60008251614037818460208701613d6b565b9190910192915050565b602081526000610c9e6020830184613d9756fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220a04acd5d02eeb8911e2a4fe28bd53f1481291334e654b0618600b13dc59cea2f64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d4366004613835565b610562565b005b6102ee6102e9366004613852565b610576565b60408051928352602083019190915201610288565b6102d9610311366004613835565b610624565b60fc54610274906001600160a01b031681565b6102d9610337366004613835565b610635565b6102ee61034a366004613894565b610646565b6102d961035d366004613835565b610784565b6102d9610370366004613835565b610795565b6102d96107a6565b6102ee61038b366004613852565b61088c565b6102d961039e3660046138f3565b610973565b6102ee6103b1366004613852565b610a10565b6102ee6103c4366004613852565b610b19565b6103dc6103d7366004613835565b610c18565b604051908152602001610288565b6102d9610ca5565b6102d9610400366004613934565b610cb9565b6102d9610d00565b6033546001600160a01b0316610274565b6102ee61042c366004613894565b610d90565b6102d961043f36600461394d565b610e7a565b61047961045236600461394d565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139f0565b6097546001600160a01b0316610274565b6102ee6104a6366004613894565b610eb0565b6102d9610f9a565b6102d96104c1366004613a50565b61104c565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613894565b6110ea565b6102d961052e366004613b04565b61120d565b6102d9610541366004613835565b6115ac565b6102d9610554366004613b75565b611635565b6103dc60fb5481565b61056a6117bf565b61057381611819565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b8613986565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610c18565b905085811015610608578095505b859250610616868686611896565b508092505050935093915050565b61062c6117bf565b61057381611bed565b61063d6117bf565b61057381611ce2565b600080828585610654611d61565b61065d83611db6565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611df6565b6106da8a8a8a8a8a611e4f565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117bf565b61057381611ed6565b61079d6117bf565b61057381611f53565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611fd0565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce613986565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b849150600061091586868661209c565b9092509050600061092585610c18565b9050828110156109695781600181610945670de0b6b3a764000085613c08565b61094f9190613c45565b6109599190613c5d565b6109639190613c74565b93508092505b5050935093915050565b61097b6117bf565b610983611df6565b61098c83611db6565b61099582611db6565b61099e816123bd565b826109b36001600160a01b03821684846123f7565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109f891815260200190565b60405180910390a350610a0b600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b50505050610b0f85858561209c565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b7d57600080fd5b505af1158015610b91573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bf557600080fd5b505af1158015610c09573d6000803e3d6000fd5b50505050610b0f858585611896565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9e9190613caf565b9392505050565b610cad6117bf565b610cb760006124be565b565b610cf76040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611fd0565b610573816124ef565b60655433906001600160a01b03168114610d875760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610573816124be565b600080828585610d9e611d61565b610da783611db6565b816001600160a01b0316836001600160a01b03161480610dd85750806001600160a01b0316836001600160a01b0316145b15610e0f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e17611df6565b610e248a8a8a8a8a611e4f565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e82611df6565b6000610e8e8383612539565b90508015610ea157610ea183838361264e565b50610eac600160c955565b5050565b600080828585610ebe611d61565b610ec783611db6565b816001600160a01b0316836001600160a01b03161480610ef85750806001600160a01b0316836001600160a01b0316145b15610f2f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f37611df6565b610f448a8a8a8a8a612b0b565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fd86040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611fd0565b610fe0611d61565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b82818114611086576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110e1576110d9878787848181106110a7576110a7613cc8565b90506020020160208101906110bc9190613835565b8686858181106110ce576110ce613cc8565b90506040020161120d565b600101611089565b50505050505050565b6000808285856110f8611d61565b61110183611db6565b816001600160a01b0316836001600160a01b031614806111325750806001600160a01b0316836001600160a01b0316145b15611169576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611171611df6565b61117e8a8a8a8a8a612b9d565b90955093508884146111bc576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61122e60405180606001604052806035815260200161405560359139611fd0565b61123783611db6565b61124082611db6565b6706f05b59d3b2000081351115611294576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d7e565b816001600160a01b0316836001600160a01b031614806112c3575061012d546001600160a01b03848116911614155b8061130b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561130857611308613986565b14155b15611342576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113546040830160208401613cf7565b600381111561136557611365613986565b1480156113725750803515155b156113a9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113bb6040830160208401613cf7565b60038111156113cc576113cc613986565b14806113f8575060016113e56040830160208401613cf7565b60038111156113f6576113f6613986565b145b801561140d575060ff546001600160a01b0316155b15611444576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff909116916114b491908a01908a01613cf7565b6040516114c49493929190613d18565b60405180910390a360006114de6040840160208501613cf7565b60038111156114ef576114ef613986565b0361154c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556115a6565b813581556115606040830160208401613cf7565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115a0576115a0613986565b02179055505b50505050565b6115b46117bf565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115fd6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff16158080156116555750600054600160ff909116105b8061166f5750303b15801561166f575060005460ff166001145b6116e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d7e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561173f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61174883611ce2565b61175486868685612c5a565b80156117b757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610cb75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d7e565b61182281611db6565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118d3576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561192757611927613986565b600381111561193857611938613986565b905250905060008160200151600381111561195557611955613986565b0361198c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a149190613caf565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613caf565b835160ff54919250906000906001600160a01b031615801590611b44575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b449190613d49565b90508015611b5157600091505b6000611b6583670de0b6b3a7640000613c45565b905083611b728287613c08565b611b7c9190613c74565b96508115611ba85786611b97670de0b6b3a76400008d613c08565b611ba19190613c74565b9750611bdf565b86600181611bbe670de0b6b3a76400008f613c08565b611bc89190613c45565b611bd29190613c5d565b611bdc9190613c74565b97505b505050505050935093915050565b6001600160a01b038116611c695760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d7e565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611ceb81611db6565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610cb7576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e485760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d7e565b600260c955565b600080611e5c8585612cf3565b611e668588612e13565b9150611e73828686610a10565b91505085811015611eba576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d7e565b611ec5848483612f5e565b9550959350505050565b600160c955565b611edf81611db6565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f5c81611db6565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab9061201c9033908690600401613de1565b602060405180830381865afa158015612039573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061205d9190613d49565b905080610eac573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d7e93929190613e03565b600080846000036120d9576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561212d5761212d613986565b600381111561213e5761213e613986565b905250905060008160200151600381111561215b5761215b613986565b03612192576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221a9190613caf565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612283573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a79190613caf565b835160ff54919250906001600160a01b031615801590612347575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612323573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123479190613d49565b15612350575060005b600061236482670de0b6b3a7640000613c45565b9050612378670de0b6b3a764000084613c08565b81612383868d613c08565b61238d9190613c08565b6123979190613c74565b9650826123a48286613c08565b6123ae9190613c74565b95505050505050935093915050565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610a0b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612fc1565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610573816130a9565b6124f8816123bd565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c19190613caf565b61012d549093508391506001600160a01b03908116908516036126465760fe54600093506125fc906001600160a01b038481169116836123f7565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061266361012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612b065760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126f2573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526127389190810190613f3c565b8151919350915060005b81811015612b015782818151811061275c5761275c613cc8565b602002602001015160000315612b0157600084828151811061278057612780613cc8565b60200260200101516001600160a01b0316636f1a30a88584815181106127a8576127a8613cc8565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127ea939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015612808573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282c9190614001565b9150508881111561283a5750875b612844818b613113565b61284e5750612b01565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa1580156128b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d59190613caf565b90508a6001600160a01b031663095ea7b38785815181106128f8576128f8613cc8565b6020026020010151846040518363ffffffff1660e01b81526004016129329291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015612951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129759190613d49565b5085838151811061298857612988613cc8565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015612a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a369190614001565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abf9190613caf565b9050612acb838c613c5d565b9a50612ad78282613c5d565b612ae19089613c45565b97508a600003612af357505050612b01565b836001019350505050612742565b505050505b6117b7565b600080612b188585612cf3565b6000612b25878787610b19565b91505087811115612b6c576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612b768682612e13565b9250612b83838787610a10565b9250612b929050858584612f5e565b509550959350505050565b600080612baa8585612cf3565b6000612bb7878787610b19565b915050612bc48682612e13565b9250808314612bff576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c43576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612c4e858589612f5e565b50909694955050505050565b600054610100900460ff16612cd75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b612ce08461324b565b612ce86132d9565b6115a683838361335e565b60ff546000906001600160a01b031615801590612d90575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d909190613d49565b905080158015612ddc575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612dda57612dda613986565b145b15610a0b576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea09190613caf565b60fe54909150612ebf906001600160a01b038481169133911687613423565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f489190613caf565b9050612f548282613c5d565b9695505050505050565b6000612f6984610c18565b905081811015612fa5576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612fba6001600160a01b03821685856123f7565b5050505050565b6000613016826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134749092919063ffffffff16565b90508051600014806130375750808060200190518101906130379190613d49565b610a0b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d7e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561317457600080fd5b505af1158015613188573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156131fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132209190613caf565b61322a9190613c08565b6132349190613c74565b905060fb54811061324457600191505b5092915050565b600054610100900460ff166132c85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6132d061348b565b61057381613510565b600054610100900460ff166133565760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb761358d565b600054610100900460ff166133db5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6133e483611f53565b6133ed82611819565b6133f6816124ef565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b03808516602483015283166044820152606481018290526115a69085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161243c565b6060613483848460008561360a565b949350505050565b600054610100900460ff166135085760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb76136fc565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b600054610100900460ff16611ecf5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6060824710156136825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d7e565b600080866001600160a01b0316858760405161369e9190614025565b60006040518083038185875af1925050503d80600081146136db576040519150601f19603f3d011682016040523d82523d6000602084013e6136e0565b606091505b50915091506136f187838387613782565b979650505050505050565b600054610100900460ff166137795760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb7336124be565b606083156137f15782516000036137ea576001600160a01b0385163b6137ea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d7e565b5081613483565b61348383838151156138065781518083602001fd5b8060405162461bcd60e51b8152600401610d7e9190614041565b6001600160a01b038116811461057357600080fd5b60006020828403121561384757600080fd5b8135610c9e81613820565b60008060006060848603121561386757600080fd5b83359250602084013561387981613820565b9150604084013561388981613820565b809150509250925092565b600080600080600060a086880312156138ac57600080fd5b853594506020860135935060408601356138c581613820565b925060608601356138d581613820565b915060808601356138e581613820565b809150509295509295909350565b60008060006060848603121561390857600080fd5b833561391381613820565b9250602084013561392381613820565b929592945050506040919091013590565b60006020828403121561394657600080fd5b5035919050565b6000806040838503121561396057600080fd5b823561396b81613820565b9150602083013561397b81613820565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c9e60208301846139b5565b60008083601f840112613a1657600080fd5b50813567ffffffffffffffff811115613a2e57600080fd5b6020830191508360208260061b8501011115613a4957600080fd5b9250929050565b600080600080600060608688031215613a6857600080fd5b8535613a7381613820565b9450602086013567ffffffffffffffff80821115613a9057600080fd5b818801915088601f830112613aa457600080fd5b813581811115613ab357600080fd5b8960208260051b8501011115613ac857600080fd5b602083019650809550506040880135915080821115613ae657600080fd5b50613af388828901613a04565b969995985093965092949392505050565b60008060008385036080811215613b1a57600080fd5b8435613b2581613820565b93506020850135613b3581613820565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b6757600080fd5b506040840190509250925092565b600080600080600060a08688031215613b8d57600080fd5b8535613b9881613820565b94506020860135613ba881613820565b93506040860135613bb881613820565b92506060860135613bc881613820565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c4057613c40613bd9565b500290565b60008219821115613c5857613c58613bd9565b500190565b600082821015613c6f57613c6f613bd9565b500390565b600082613caa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613cc157600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613d0957600080fd5b813560048110610c9e57600080fd5b8481526020810184905260808101613d3360408301856139b5565b613d4060608301846139b5565b95945050505050565b600060208284031215613d5b57600080fd5b81518015158114610c9e57600080fd5b60005b83811015613d86578181015183820152602001613d6e565b838111156115a65750506000910152565b60008151808452613daf816020860160208601613d6b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134836040830184613d97565b60006001600160a01b03808616835280851660208401525060606040830152613d406060830184613d97565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613ea557613ea5613e2f565b604052919050565b600067ffffffffffffffff821115613ec757613ec7613e2f565b5060051b60200190565b600082601f830112613ee257600080fd5b81516020613ef7613ef283613ead565b613e5e565b82815260059290921b84018101918181019086841115613f1657600080fd5b8286015b84811015613f315780518352918301918301613f1a565b509695505050505050565b60008060408385031215613f4f57600080fd5b825167ffffffffffffffff80821115613f6757600080fd5b818501915085601f830112613f7b57600080fd5b81516020613f8b613ef283613ead565b82815260059290921b84018101918181019089841115613faa57600080fd5b948201945b83861015613fd1578551613fc281613820565b82529482019490820190613faf565b91880151919650909350505080821115613fea57600080fd5b50613ff785828601613ed1565b9150509250929050565b6000806040838503121561401457600080fd5b505080516020909101519092909150565b60008251614037818460208701613d6b565b9190910192915050565b602081526000610c9e6020830184613d9756fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220a04acd5d02eeb8911e2a4fe28bd53f1481291334e654b0618600b13dc59cea2f64736f6c634300080d0033", "devdoc": { "author": "Venus", "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", @@ -1548,6 +1548,7 @@ "initialize(address,address,address,address,uint256)": { "params": { "accessControlManager_": "Access control manager contract address", + "baseAsset_": "Address of the base asset", "destinationAddress_": "Address at all incoming tokens will transferred to", "minAmountToConvert_": "Minimum amount to convert", "priceOracle_": "Resilient oracle address" @@ -1854,7 +1855,7 @@ "notice": "To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)" }, "getAmountOut(uint256,address,address)": { - "notice": "To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)" + "notice": "To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut" }, "getUpdatedAmountIn(uint256,address,address)": { "notice": "To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut" @@ -2020,7 +2021,7 @@ "label": "conversionConfigurations", "offset": 0, "slot": "253", - "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5463_storage))" + "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5478_storage))" }, { "astId": 3371, @@ -2055,7 +2056,7 @@ "type": "t_array(t_uint256)45_storage" }, { - "astId": 6813, + "astId": 6828, "contract": "contracts/TokenConverter/SingleTokenConverter.sol:SingleTokenConverter", "label": "baseAsset", "offset": 0, @@ -2107,31 +2108,31 @@ "label": "contract ResilientOracle", "numberOfBytes": "20" }, - "t_enum(ConversionAccessibility)5455": { + "t_enum(ConversionAccessibility)5470": { "encoding": "inplace", "label": "enum IAbstractTokenConverter.ConversionAccessibility", "numberOfBytes": "1" }, - "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5463_storage))": { + "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5478_storage))": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => mapping(address => struct IAbstractTokenConverter.ConversionConfig))", "numberOfBytes": "32", - "value": "t_mapping(t_address,t_struct(ConversionConfig)5463_storage)" + "value": "t_mapping(t_address,t_struct(ConversionConfig)5478_storage)" }, - "t_mapping(t_address,t_struct(ConversionConfig)5463_storage)": { + "t_mapping(t_address,t_struct(ConversionConfig)5478_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct IAbstractTokenConverter.ConversionConfig)", "numberOfBytes": "32", - "value": "t_struct(ConversionConfig)5463_storage" + "value": "t_struct(ConversionConfig)5478_storage" }, - "t_struct(ConversionConfig)5463_storage": { + "t_struct(ConversionConfig)5478_storage": { "encoding": "inplace", "label": "struct IAbstractTokenConverter.ConversionConfig", "members": [ { - "astId": 5458, + "astId": 5473, "contract": "contracts/TokenConverter/SingleTokenConverter.sol:SingleTokenConverter", "label": "incentive", "offset": 0, @@ -2139,12 +2140,12 @@ "type": "t_uint256" }, { - "astId": 5462, + "astId": 5477, "contract": "contracts/TokenConverter/SingleTokenConverter.sol:SingleTokenConverter", "label": "conversionAccess", "offset": 0, "slot": "1", - "type": "t_enum(ConversionAccessibility)5455" + "type": "t_enum(ConversionAccessibility)5470" } ], "numberOfBytes": "64" diff --git a/deployments/bsctestnet/solcInputs/e9f683aad829bf9574e4eef6b067ab3e.json b/deployments/bsctestnet/solcInputs/e9f683aad829bf9574e4eef6b067ab3e.json new file mode 100644 index 00000000..46bd1909 --- /dev/null +++ b/deployments/bsctestnet/solcInputs/e9f683aad829bf9574e4eef6b067ab3e.json @@ -0,0 +1,123 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides 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} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling 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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\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.9.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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlledV8\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\n /// @notice Access control manager contract\n IAccessControlManagerV8 private _accessControlManager;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when access control manager contract address is changed\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n /// @notice Thrown when the action is prohibited by AccessControlManager\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Sets the address of AccessControlManager\n * @dev Admin function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n * @custom:event Emits NewAccessControlManager event\n * @custom:access Only Governance\n */\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Returns the address of the access control manager contract\n */\n function accessControlManager() external view returns (IAccessControlManagerV8) {\n return _accessControlManager;\n }\n\n /**\n * @dev Internal function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n */\n function _setAccessControlManager(address accessControlManager_) internal {\n require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n address oldAccessControlManager = address(_accessControlManager);\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title IAccessControlManagerV8\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\n */\ninterface IAccessControlManagerV8 is IAccessControl {\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) external;\n\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface OracleInterface {\n function getPrice(address asset) external view returns (uint256);\n}\n\ninterface ResilientOracleInterface is OracleInterface {\n function updatePrice(address vToken) external;\n\n function updateAssetPrice(address asset) external;\n\n function getUnderlyingPrice(address vToken) external view returns (uint256);\n}\n\ninterface TwapInterface is OracleInterface {\n function updateTwap(address asset) external returns (uint256);\n}\n\ninterface BoundValidatorInterface {\n function validatePriceWithAnchorPrice(\n address asset,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface VBep20Interface is IERC20Metadata {\n /**\n * @notice Underlying asset for this VToken\n */\n function underlying() external view returns (address);\n}\n" + }, + "@venusprotocol/oracle/contracts/ResilientOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"./interfaces/VBep20Interface.sol\";\nimport \"./interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ResilientOracle\n * @author Venus\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\n * \n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\n * for attacking the protocol.\n * \n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\n * \n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \n * \n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\n * market. The upper bound ratio represents the deviation between reported price (the price that’s being\n * validated) and the anchor price (the price we are validating against) above which the reported price will\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\n * should be true:\n\n```\nanchorRatio = anchorPrice/reporterPrice\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\n```\n\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \n * \n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\n * oracle to be stagnant and treat it like it's disabled.\n */\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\n /**\n * @dev Oracle roles:\n * **main**: The most trustworthy price source\n * **pivot**: Price oracle used as a loose sanity checker\n * **fallback**: The backup source when main oracle price is invalidated\n */\n enum OracleRole {\n MAIN,\n PIVOT,\n FALLBACK\n }\n\n struct TokenConfig {\n /// @notice asset address\n address asset;\n /// @notice `oracles` stores the oracles based on their role in the following order:\n /// [main, pivot, fallback],\n /// It can be indexed with the corresponding enum OracleRole value\n address[3] oracles;\n /// @notice `enableFlagsForOracles` stores the enabled state\n /// for each oracle in the same order as `oracles`\n bool[3] enableFlagsForOracles;\n }\n\n uint256 public constant INVALID_PRICE = 0;\n\n /// @notice Native market address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable nativeMarket;\n\n /// @notice VAI address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vai;\n\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\n /// and can serve as any underlying asset of a market that supports native tokens\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Bound validator contract address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n BoundValidatorInterface public immutable boundValidator;\n\n mapping(address => TokenConfig) private tokenConfigs;\n\n event TokenConfigAdded(\n address indexed asset,\n address indexed mainOracle,\n address indexed pivotOracle,\n address fallbackOracle\n );\n\n /// Event emitted when an oracle is set\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\n\n /// Event emitted when an oracle is enabled or disabled\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\n\n /**\n * @notice Checks whether an address is null or not\n */\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /**\n * @notice Checks whether token config exists by checking whether asset is null address\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\n * @param asset asset address\n */\n modifier checkTokenConfigExistence(address asset) {\n if (tokenConfigs[asset].asset == address(0)) revert(\"token config must exist\");\n _;\n }\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\n /// (e.g vETH on ethereum would not be supported, only vWETH)\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\n /// Set to address(0) of VAI is not existent.\n /// @param _boundValidator Address of the bound validator contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address nativeMarketAddress,\n address vaiAddress,\n BoundValidatorInterface _boundValidator\n ) notNullAddress(address(_boundValidator)) {\n nativeMarket = nativeMarketAddress;\n vai = vaiAddress;\n boundValidator = _boundValidator;\n\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract admin and sets the BoundValidator contract address\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n }\n\n /**\n * @notice Pauses oracle\n * @custom:access Only Governance\n */\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n _pause();\n }\n\n /**\n * @notice Unpauses oracle\n * @custom:access Only Governance\n */\n function unpause() external {\n _checkAccessAllowed(\"unpause()\");\n _unpause();\n }\n\n /**\n * @notice Batch sets token configs\n * @param tokenConfigs_ Token config array\n * @custom:access Only Governance\n * @custom:error Throws a length error if the length of the token configs array is 0\n */\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\n if (tokenConfigs_.length == 0) revert(\"length can't be 0\");\n uint256 numTokenConfigs = tokenConfigs_.length;\n for (uint256 i; i < numTokenConfigs; ) {\n setTokenConfig(tokenConfigs_[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Sets oracle for a given asset and role.\n * @dev Supplied asset **must** exist and main oracle may not be null\n * @param asset Asset address\n * @param oracle Oracle address\n * @param role Oracle role\n * @custom:access Only Governance\n * @custom:error Null address error if main-role oracle address is null\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\n */\n function setOracle(\n address asset,\n address oracle,\n OracleRole role\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"setOracle(address,address,uint8)\");\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\"can't set zero address to main oracle\");\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\n emit OracleSet(asset, oracle, uint256(role));\n }\n\n /**\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\n * @param asset Asset address\n * @param role Oracle role\n * @param enable Enabled boolean of the oracle\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n */\n function enableOracle(\n address asset,\n OracleRole role,\n bool enable\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"enableOracle(address,uint8,bool)\");\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\n emit OracleEnabled(asset, uint256(role), enable);\n }\n\n /**\n * @notice Updates the TWAP pivot oracle price.\n * @dev This function should always be called before calling getUnderlyingPrice\n * @param vToken vToken address\n */\n function updatePrice(address vToken) external override {\n address asset = _getUnderlyingAsset(vToken);\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @notice Updates the pivot oracle price. Currently using TWAP\n * @dev This function should always be called before calling getPrice\n * @param asset asset address\n */\n function updateAssetPrice(address asset) external {\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @dev Gets token config by asset address\n * @param asset asset address\n * @return tokenConfig Config for the asset\n */\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\n return tokenConfigs[asset];\n }\n\n /**\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\n * - Check if the oracle is paused globally\n * - Validate price from main oracle against pivot oracle\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\n * - Validate price from main oracle against fallback oracle if the second validation failed\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\n * main oracle price is returned.\n * @param vToken vToken address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n\n address asset = _getUnderlyingAsset(vToken);\n return _getPrice(asset);\n }\n\n /**\n * @notice Gets price of the asset\n * @param asset asset address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getPrice(address asset) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n return _getPrice(asset);\n }\n\n /**\n * @notice Sets/resets single token configs.\n * @dev main oracle **must not** be a null address\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress is thrown if asset address is null\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(\n tokenConfig.asset,\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\n );\n }\n\n /**\n * @notice Gets oracle and enabled status by asset address\n * @param asset asset address\n * @param role Oracle role\n * @return oracle Oracle address based on role\n * @return enabled Enabled flag of the oracle based on token config\n */\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\n oracle = tokenConfigs[asset].oracles[uint256(role)];\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\n }\n\n function _getPrice(address asset) internal view returns (uint256) {\n uint256 pivotPrice = INVALID_PRICE;\n\n // Get pivot oracle price, Invalid price if not available or error\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracleEnabled && pivotOracle != address(0)) {\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\n pivotPrice = pricePivot;\n } catch {}\n }\n\n // Compare main price and pivot price, return main price and if validation was successful\n // note: In case pivot oracle is not available but main price is available and\n // validation is successful, the main oracle price is returned.\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\n asset,\n pivotPrice,\n pivotOracleEnabled && pivotOracle != address(0)\n );\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\n\n // Compare fallback and pivot if main oracle comparision fails with pivot\n // Return fallback price when fallback price is validated successfully with pivot oracle\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\n\n // Lastly compare main price and fallback price\n if (\n mainPrice != INVALID_PRICE &&\n fallbackPrice != INVALID_PRICE &&\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\n ) {\n return mainPrice;\n }\n\n revert(\"invalid resilient oracle price\");\n }\n\n /**\n * @notice Gets a price for the provided asset\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\n * able to fetch a correct price\n * @param asset asset address\n * @param pivotPrice Pivot oracle price\n * @param pivotEnabled If pivot oracle is not empty and enabled\n * @return price USD price in scaled decimals\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\n * @return pivotValidated Boolean representing if the validation of main oracle price\n * and pivot oracle price were successful\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\n * address is null\n */\n function _getMainOraclePrice(\n address asset,\n uint256 pivotPrice,\n bool pivotEnabled\n ) internal view returns (uint256, bool) {\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\n if (mainOracleEnabled && mainOracle != address(0)) {\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\n if (!pivotEnabled) {\n return (mainOraclePrice, true);\n }\n if (pivotPrice == INVALID_PRICE) {\n return (mainOraclePrice, false);\n }\n return (\n mainOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\n * @param asset asset address\n * @return price USD price in 18 decimals\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\n * and pivot oracle price were successfull\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\n * address is null\n */\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\n if (fallbackEnabled && fallbackOracle != address(0)) {\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\n if (pivotPrice == INVALID_PRICE) {\n return (fallbackOraclePrice, false);\n }\n return (\n fallbackOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function returns the underlying asset of a vToken\n * @param vToken vToken address\n * @return asset underlying asset address\n */\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\n if (vToken == nativeMarket) {\n asset = NATIVE_TOKEN_ADDR;\n } else if (vToken == vai) {\n asset = vai;\n } else {\n asset = VBep20Interface(vToken).underlying();\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\nuint256 constant EXP_SCALE = 1e18;\n\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\nuint256 constant MANTISSA_ONE = EXP_SCALE;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\n" + }, + "@venusprotocol/solidity-utilities/contracts/validators.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\nerror ZeroAddressNotAllowed();\n\n/// @notice Thrown if the supplied value is 0 where it is not allowed\nerror ZeroValueNotAllowed();\n\n/// @notice Checks if the provided address is nonzero, reverts otherwise\n/// @param address_ Address to check\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\nfunction ensureNonzeroAddress(address address_) pure {\n if (address_ == address(0)) {\n revert ZeroAddressNotAllowed();\n }\n}\n\n/// @notice Checks if the provided value is nonzero, reverts otherwise\n/// @param value_ Value to check\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\nfunction ensureNonzeroValue(uint256 value_) pure {\n if (value_ == 0) {\n revert ZeroValueNotAllowed();\n }\n}\n" + }, + "contracts/Interfaces/IComptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IComptroller {\n function isComptroller() external view returns (bool);\n\n function markets(address) external view returns (bool);\n\n function getAllMarkets() external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IConverterNetwork.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAbstractTokenConverter } from \"../TokenConverter/IAbstractTokenConverter.sol\";\n\n/**\n * @title IConverterNetwork\n * @author Venus\n * @notice Interface implemented by `ConverterNetwork`.\n */\ninterface IConverterNetwork {\n /// @notice Adds new converter to the array\n /// @param _tokenConverter Address of the token converter\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Removes converter from the array\n /// @param _tokenConverter Address of the token converter\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice This function returns the array containing all the converters addresses\n /// @return Array containing all the converters addresses\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\n\n /// @notice This function checks for given address is converter or not\n /// @param _tokenConverter Address of the token converter\n /// @return boolean true if given address is converter otherwise false\n function isTokenConverter(address _tokenConverter) external view returns (bool);\n}\n" + }, + "contracts/Interfaces/IPoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IPoolRegistry {\n /// @notice Get VToken in the Pool for an Asset\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\n\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IRiskFund.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IRiskFund\n * @author Venus\n * @notice Interface implemented by `RiskFund`.\n */\ninterface IRiskFund {\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updatePoolState(\n address comptroller,\n address asset,\n uint256 amount\n ) external;\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n\n/**\n * @title IRiskFundGetters\n * @author Venus\n * @notice Interface implemented by `RiskFund` for getter methods.\n */\ninterface IRiskFundGetters {\n function convertibleBaseAsset() external view returns (address);\n}\n" + }, + "contracts/Interfaces/IVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IVToken {\n function underlying() external view returns (address);\n}\n" + }, + "contracts/Test/Mocks/MockConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\n\nimport { AbstractTokenConverter } from \"../../TokenConverter/AbstractTokenConverter.sol\";\nimport { IRiskFundGetters } from \"../../Interfaces/IRiskFund.sol\";\n\ncontract MockConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) public assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) public poolsAssetsReserves;\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n function mockPrivateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 balanceDiff\n ) external {\n _privateConversion(comptroller, tokenAddressOut, balanceDiff);\n }\n\n function AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) public initializer {\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n assetsReserves[tokenAddressIn] += convertedTokenInBalance;\n poolsAssetsReserves[comptroller][tokenAddressIn] += convertedTokenInBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @notice Get base asset address\n function _getDestinationBaseAsset() internal view override returns (address) {\n return IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/Test/Mocks/MockRiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { RiskFundConverter } from \"../../TokenConverter/RiskFundConverter.sol\";\n\ncontract MockRiskFundConverter is RiskFundConverter {\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) RiskFundConverter(corePoolComptroller_, vBNB_, nativeWrapped_) {}\n\n function postConversionHookMock(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) external {\n super._postConversionHook(tokenInAddress, tokenOutAddress, amountIn, amountOut);\n }\n\n function preTransferHookMock(address tokenOutAddress, uint256 amountOut) external {\n super._preTransferHook(tokenOutAddress, amountOut);\n }\n\n function setAssetsReserves(address asset, uint256 amount) external {\n assetsReserves[asset] = amount;\n }\n\n function setPoolsAssetsReserves(\n address comptroller,\n address asset,\n uint256 amount\n ) external {\n poolsAssetsReserves[comptroller][asset] = amount;\n }\n\n function getPoolsAssetsReserves(address comptroller, address asset) external view returns (uint256) {\n return poolsAssetsReserves[comptroller][asset];\n }\n\n function getAssetsReserves(address asset) external view returns (uint256) {\n return assetsReserves[asset];\n }\n}\n" + }, + "contracts/TokenConverter/AbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { MANTISSA_ONE, EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\nimport { IAbstractTokenConverter } from \"./IAbstractTokenConverter.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @title AbstractTokenConverter\n/// @author Venus\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\n/*\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\n *\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\n * a. convertExactTokensSupportingFeeOnTransferTokens\n * b. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\n * similar to Case I.\n *\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * a. convertExactTokens\n * b. convertForExactTokens\n * c. convertExactTokensSupportingFeeOnTransferTokens\n * d. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * similar to Case III.\n *\n * ------------------------------------------------------------------------------------------------------------------------------------\n * Example 1:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInAmount - 100\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\n * function for tokenIn as deflationary token.\n *\n * Example 2:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\n * tokenOutAmount - 70\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\n * ------------------------------------------------------------------------------------------------------------------------------------\n *\n * This contract also supports private conversion between the converters:\n * Private conversions:\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\n *\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\n *\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\n * tokenAddressOut: As base asset of that converter.\n *\n * ConverterNetwork:\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\n * and tokenAddressOut provided.\n *\n * findTokenConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\n *\n * findTokenConvertersForConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\n */\n\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Maximum incentive could be\n uint256 public constant MAX_INCENTIVE = 0.5e18;\n\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\n uint256 public minAmountToConvert;\n\n /// @notice Venus price oracle contract\n ResilientOracle public priceOracle;\n\n /// @notice conversion configurations for the existing pairs\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\n\n /// @notice Address that all incoming tokens are transferred to\n address public destinationAddress;\n\n /// @notice Boolean for if conversion is paused\n bool public conversionPaused;\n\n /// @notice Address of the converterNetwork contract\n IConverterNetwork public converterNetwork;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n uint256[45] private __gap;\n\n /// @notice Emitted when config is updated for tokens pair\n event ConversionConfigUpdated(\n address indexed tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 oldIncentive,\n uint256 newIncentive,\n ConversionAccessibility oldAccess,\n ConversionAccessibility newAccess\n );\n /// @notice Emitted when price oracle address is updated\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\n\n /// @notice Emitted when destination address is updated\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\n\n /// @notice Emitted when converterNetwork address is updated\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\n\n /// @notice Emitted when exact amount of tokens are converted for tokens\n event ConvertedExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens\n event ConvertedForExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when conversion is paused\n event ConversionPaused(address indexed sender);\n\n /// @notice Emitted when conversion is unpaused\n event ConversionResumed(address indexed sender);\n\n /// @notice Event emitted when tokens are swept\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\n error AmountOutMismatched();\n\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\n error AmountInMismatched();\n\n /// @notice Thrown when given input amount is zero\n error InsufficientInputAmount();\n\n /// @notice Thrown when given output amount is zero\n error InsufficientOutputAmount();\n\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\n error ConversionConfigNotEnabled();\n\n /// @notice Thrown when conversion is enabled only for private conversions\n error ConversionEnabledOnlyForPrivateConversions();\n\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n error InvalidToAddress();\n\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\n\n /// @notice Thrown when amountOut is lower than amountOutMin\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\n\n /// @notice Thrown when amountIn is higher than amountInMax\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\n\n /// @notice Thrown when conversion is paused\n error ConversionTokensPaused();\n\n /// @notice Thrown when conversion is Active\n error ConversionTokensActive();\n\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\n error InvalidTokenConfigAddresses();\n\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\n error InsufficientPoolLiquidity();\n\n /// @notice When address of the ConverterNetwork is not set or Zero address\n error InvalidConverterNetwork();\n\n /// @notice Thrown when trying to set non zero incentive for private conversion\n error NonZeroIncentiveForPrivateConversion();\n\n /// @notice Thrown when using convertForExactTokens deflationary tokens\n error DeflationaryTokenNotSupported();\n\n /// @notice Thrown when minimum amount to convert is zero\n error InvalidMinimumAmountToConvert();\n\n /// @notice Thrown when there is a mismatch in the length of input arrays\n error InputLengthMisMatch();\n\n /**\n * @notice Modifier to ensure valid conversion parameters for a token conversion\n * and check if conversion is paused or not\n * @param to The recipient address for the converted tokens\n * @param tokenAddressIn The input token address for the conversion\n * @param tokenAddressOut The output token address for the conversion\n */\n modifier validConversionParameters(\n address to,\n address tokenAddressIn,\n address tokenAddressOut\n ) {\n _checkConversionPaused();\n ensureNonzeroAddress(to);\n if (to == tokenAddressIn || to == tokenAddressOut) {\n revert InvalidToAddress();\n }\n _;\n }\n\n /// @notice Pause conversion of tokens\n /// @custom:event Emits ConversionPaused on success\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\n /// @custom:access Restricted by ACM\n function pauseConversion() external {\n _checkAccessAllowed(\"pauseConversion()\");\n _checkConversionPaused();\n conversionPaused = true;\n emit ConversionPaused(msg.sender);\n }\n\n /// @notice Resume conversion of tokens.\n /// @custom:event Emits ConversionResumed on success\n /// @custom:error ConversionTokensActive thrown when conversion is already active\n /// @custom:access Restricted by ACM\n function resumeConversion() external {\n _checkAccessAllowed(\"resumeConversion()\");\n if (!conversionPaused) {\n revert ConversionTokensActive();\n }\n\n conversionPaused = false;\n emit ConversionResumed(msg.sender);\n }\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:access Only Governance\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\n _setPriceOracle(priceOracle_);\n }\n\n /// @notice Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:access Only Governance\n function setDestination(address destinationAddress_) external onlyOwner {\n _setDestination(destinationAddress_);\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:access Only Governance\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\n _setConverterNetwork(converterNetwork_);\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:access Only Governance\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n _setMinAmountToConvert(minAmountToConvert_);\n }\n\n /// @notice Batch sets the conversion configurations\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressesOut Array of addresses of tokenOut\n /// @param conversionConfigs Array of conversionConfig config details to update\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\n function setConversionConfigs(\n address tokenAddressIn,\n address[] calldata tokenAddressesOut,\n ConversionConfig[] calldata conversionConfigs\n ) external {\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\n\n for (uint256 i; i < tokenOutArrayLength; ) {\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountIn != amountInMantissa) {\n revert AmountInMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\n /// otherwise the amount is adjusted\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountOut != amountOutMantissa) {\n revert AmountOutMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\n /// @param tokenAddress The address of the ERC-20 token to sweep\n /// @param to The address to which tokens will be transferred\n /// @param amount The amount to transfer\n /// @custom:event Emits SweepToken event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\n /// @custom:access Only Governance\n function sweepToken(\n address tokenAddress,\n address to,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(to);\n ensureNonzeroValue(amount);\n\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n preSweepToken(tokenAddress, amount);\n token.safeTransfer(to, amount);\n\n emit SweepToken(tokenAddress, to, amount);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\n /// @dev This function retrieves values without altering token prices\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n amountConvertedMantissa = amountInMantissa;\n uint256 tokenInToOutConversion;\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountConvertedMantissa =\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\n tokenInToOutConversion; //round-up\n amountOutMantissa = maxTokenOutReserve;\n }\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @dev This function retrieves values without altering token prices\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountOutMantissa = maxTokenOutReserve;\n }\n\n amountConvertedMantissa = amountOutMantissa;\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountInMantissa;\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountOutMantissa;\n }\n\n /// @notice This method updated the states of this contract after getting funds from PSR\n /// after settling the amount(if any) through privateConversion between converters\n /// @dev This function is called by protocolShareReserve\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\n if (balanceDiff > 0) {\n _privateConversion(comptroller, asset, balanceDiff);\n }\n }\n\n /// @notice Set the configuration for new or existing conversion pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n /// @custom:event Emits ConversionConfigUpdated event on success\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\n /// @custom:access Controlled by AccessControlManager\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) public {\n _checkAccessAllowed(\"setConversionConfig(address,address,ConversionConfig)\");\n ensureNonzeroAddress(tokenAddressIn);\n ensureNonzeroAddress(tokenAddressOut);\n\n if (conversionConfig.incentive > MAX_INCENTIVE) {\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\n }\n\n if (\n (tokenAddressIn == tokenAddressOut) ||\n (tokenAddressIn != _getDestinationBaseAsset()) ||\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\n ) {\n revert InvalidTokenConfigAddresses();\n }\n\n if (\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\n conversionConfig.incentive != 0\n ) {\n revert NonZeroIncentiveForPrivateConversion();\n }\n\n if (\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\n (address(converterNetwork) == address(0))\n ) {\n revert InvalidConverterNetwork();\n }\n\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n emit ConversionConfigUpdated(\n tokenAddressIn,\n tokenAddressOut,\n configuration.incentive,\n conversionConfig.incentive,\n configuration.conversionAccess,\n conversionConfig.conversionAccess\n );\n\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\n } else {\n configuration.incentive = conversionConfig.incentive;\n configuration.conversionAccess = conversionConfig.conversionAccess;\n }\n }\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\n\n /// @dev Operations to perform before sweeping tokens\n /// @param token Address of the token\n /// @param amount Amount transferred to address(to)\n function preSweepToken(address token, uint256 amount) internal virtual {}\n\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function _convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n if (amountOutMantissa < amountOutMinMantissa) {\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n }\n\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\n /// it is called by convertForExactTokens function\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n if (actualAmountIn != amountInMantissa) {\n revert DeflationaryTokenNotSupported();\n }\n\n if (actualAmountIn > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n actualAmountOut = amountOutMantissa;\n }\n\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n if (amountInMantissa > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\n }\n\n /// @dev return actualAmountOut from reserves for tokenAddressOut\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\n function _doTransferOut(\n address tokenAddressOut,\n address to,\n uint256 amountConvertedMantissa\n ) internal {\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountConvertedMantissa) {\n revert InsufficientPoolLiquidity();\n }\n\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\n\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\n tokenOut.safeTransfer(to, amountConvertedMantissa);\n }\n\n /// @notice Transfer tokenAddressIn from user to destination\n /// @param tokenAddressIn Address of the token to convert\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @return actualAmountIn Actual amount transferred to destination\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\n }\n\n /// @dev Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:event Emits PriceOracleUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\n ensureNonzeroAddress(address(priceOracle_));\n emit PriceOracleUpdated(priceOracle, priceOracle_);\n priceOracle = priceOracle_;\n }\n\n /// @dev Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:event Emits DestinationAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\n function _setDestination(address destinationAddress_) internal {\n ensureNonzeroAddress(destinationAddress_);\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\n destinationAddress = destinationAddress_;\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\n ensureNonzeroAddress(address(converterNetwork_));\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\n converterNetwork = converterNetwork_;\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:event MinAmountToConvertUpdated is emitted in success\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\n ensureNonzeroValue(minAmountToConvert_);\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\n minAmountToConvert = minAmountToConvert_;\n }\n\n /// @dev Hook to perform after converting tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param amountIn Amount of tokenIn converted\n /// @param amountOut Amount of tokenOut converted\n function _postConversionHook(\n address tokenAddressIn,\n address tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n ) internal virtual {}\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init_unchained(\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n _setPriceOracle(priceOracle_);\n _setDestination(destinationAddress_);\n _setMinAmountToConvert(minAmountToConvert_);\n conversionPaused = false;\n }\n\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return Amount of asset, for _privateConversion\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\n\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\n /// destination contract as destination's base asset\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\n function _privateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 amountToConvert\n ) internal {\n address tokenAddressIn = _getDestinationBaseAsset();\n address _destinationAddress = destinationAddress;\n uint256 convertedTokenInBalance;\n if (address(converterNetwork) != address(0)) {\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\n uint256 convertersLength = converterAddresses.length;\n for (uint256 i; i < convertersLength; ) {\n if (converterBalances[i] == 0) break;\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\n converterBalances[i],\n tokenAddressOut,\n tokenAddressIn\n );\n if (amountIn > amountToConvert) {\n amountIn = amountToConvert;\n }\n\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\n break;\n }\n\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\n amountIn,\n 0,\n tokenAddressOut,\n tokenAddressIn,\n _destinationAddress\n );\n\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n amountToConvert -= amountIn;\n convertedTokenInBalance += (balanceAfter - balanceBefore);\n\n if (amountToConvert == 0) break;\n unchecked {\n ++i;\n }\n }\n }\n\n _postPrivateConversionHook(\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance,\n tokenAddressOut,\n amountToConvert\n );\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal virtual {}\n\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\n\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\n /// @param amountIn The amount to convert\n /// @param tokenAddress Address of the token\n /// @return isValid true if amount to convert is greater than minimum amount to convert\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\n priceOracle.updateAssetPrice(tokenAddress);\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\n\n if (amountInInUsd >= minAmountToConvert) {\n isValid = true;\n }\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\n if (amountInMantissa == 0) {\n revert InsufficientInputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\n /// multiplied by conversionWithIncentive which will be >= 1\n amountOutMantissa =\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\n (tokenOutUnderlyingPrice * EXP_SCALE);\n\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n }\n\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\n if (amountOutMantissa == 0) {\n revert InsufficientOutputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\n converterNetwork.isTokenConverter(msg.sender);\n if (isPrivateConversion) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\n if (isPrivateConversion) {\n amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion;\n } else {\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\n }\n }\n\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\n if (\n (!(isConverter) &&\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n }\n\n /// @dev To check, is conversion paused\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\n function _checkConversionPaused() internal view {\n if (conversionPaused) {\n revert ConversionTokensPaused();\n }\n }\n\n /// @dev Get base asset address of the destination contract\n /// @return Address of the base asset\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\n}\n" + }, + "contracts/TokenConverter/IAbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @notice Interface for AbstractTokenConverter\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ninterface IAbstractTokenConverter {\n /// @notice This enum define the all possible ways of conversion can happen\n enum ConversionAccessibility {\n NONE, // Conversion is disable for the pair\n ALL, // Conversion is enable for private conversion and users\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\n ONLY_FOR_USERS // Conversion is enable only for users\n }\n\n /// @notice This struct represents the configuration for a token conversion.\n struct ConversionConfig {\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\n uint256 incentive;\n /// enable or disable conversion for users or converters or both or none\n ConversionAccessibility conversionAccess;\n }\n\n /// @notice Pause conversion of tokens\n function pauseConversion() external;\n\n /// @notice Resume conversion of tokens.\n function resumeConversion() external;\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n function setPriceOracle(ResilientOracle priceOracle_) external;\n\n /// @notice Set the configuration for new or existing convert pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) external;\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Get the configuration for the pair of the tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\n /// @return conversionAccess Accessibility for the pair of tokens\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\n external\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\n\n /// @notice Get the address of the converterNetwork\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) external view returns (uint256 tokenBalance);\n}\n" + }, + "contracts/TokenConverter/RiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\nimport { IPoolRegistry } from \"../Interfaces/IPoolRegistry.sol\";\nimport { IComptroller } from \"../Interfaces/IComptroller.sol\";\nimport { IRiskFund, IRiskFundGetters } from \"../Interfaces/IRiskFund.sol\";\nimport { IVToken } from \"../Interfaces/IVToken.sol\";\n\n/// @title RiskFundConverter\n/// @author Venus\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the core pool comptroller\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n ///@notice Address of the vBNB\n ///@dev This address is used to include the BNB market while in getPools method\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable VBNB;\n\n ///@notice Address of the native wrapped currency\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_WRAPPED;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) internal assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\n\n /// @notice Address of pool registry contract\n address public poolRegistry;\n\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\n\n // Error thrown when comptrollers array length is not equal to assets array length\n error InvalidArguments();\n\n /// @notice thrown when amount entered is greater than balance\n error InsufficientBalance();\n\n /// @notice thrown when asset does not exist in the pool\n error MarketNotExistInPool(address comptroller, address asset);\n\n /// @notice thrown to prevent reentrancy\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\n /// cannot be called recursively within the same transaction.\n error ReentrancyGuardError();\n\n /// @param corePoolComptroller_ Address of the Comptroller pool\n /// @param vBNB_ Address of the vBNB\n /// @param nativeWrapped_ Address of the wrapped native currency\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) {\n ensureNonzeroAddress(corePoolComptroller_);\n ensureNonzeroAddress(vBNB_);\n ensureNonzeroAddress(nativeWrapped_);\n\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\n VBNB = vBNB_;\n NATIVE_WRAPPED = nativeWrapped_;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param poolRegistry_ Address of the pool registry\n /// @param minAmountToConvert_ minimum amount to convert\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address poolRegistry_,\n uint256 minAmountToConvert_,\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) public initializer {\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n ensureNonzeroAddress(poolRegistry_);\n poolRegistry = poolRegistry_;\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Pool registry setter\n /// @param poolRegistry_ Address of the pool registry\n /// @custom:event PoolRegistryUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:access Only Governance\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\n poolRegistry = poolRegistry_;\n }\n\n /// @notice Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:access Restricted by ACM\n function setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) external {\n _checkAccessAllowed(\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\");\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return reserves Asset's reserve in risk fund\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n reserves = poolsAssetsReserves[comptroller][asset];\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Reserves of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n tokenBalance = assetsReserves[tokenAddress];\n }\n\n /// @notice Get the array of all pools addresses\n /// @param tokenAddress Address of the token\n /// @return poolsWithCore Array of the pools addresses in which token is available\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\n\n if (isAssetListedInCore(tokenAddress)) {\n uint256 poolsLength = poolsWithCore.length;\n address[] memory extendedPools = new address[](poolsLength + 1);\n\n for (uint256 i; i < poolsLength; ) {\n extendedPools[i] = poolsWithCore[i];\n unchecked {\n ++i;\n }\n }\n\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\n poolsWithCore = extendedPools;\n }\n }\n\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\n assetsReserves[tokenOutAddress] -= amountOut;\n }\n\n /// @notice Hook to perform after converting tokens\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\n /// @param tokenInAddress Address of the tokenIn\n /// @param tokenOutAddress Address of the tokenOut\n /// @param amountIn Amount of tokenIn transferred\n /// @param amountOut Amount of tokenOut transferred\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\n function _postConversionHook(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) internal override {\n address[] memory pools = getPools(tokenOutAddress);\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\n ensureNonzeroValue(assetReserve);\n\n uint256 poolsLength = pools.length;\n uint256 distributedOutShare;\n uint256 poolAmountInShare;\n uint256 distributedInShare;\n\n for (uint256 i; i < poolsLength; ) {\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\n if (currentPoolsAssetsReserves != 0) {\n if (i < (poolsLength - 1)) {\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\n distributedInShare += poolAmountInShare;\n } else {\n uint256 distributedDiff = amountOut - distributedOutShare;\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\n poolAmountInShare = amountIn - distributedInShare;\n }\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\n }\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Operations to perform before sweeping tokens\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\n if (amount > balance) revert InsufficientBalance();\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\n\n if (balanceDiff < amount) {\n uint256 amountDiff;\n unchecked {\n amountDiff = amount - balanceDiff;\n }\n\n address[] memory pools = getPools(tokenAddress);\n uint256 assetReserve = assetsReserves[tokenAddress];\n uint256 poolsLength = pools.length;\n uint256 distributedShare;\n\n for (uint256 i; i < poolsLength; ) {\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\n if (i < (poolsLength - 1)) {\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\n } else {\n uint256 distributedDiff = amountDiff - distributedShare;\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\n }\n }\n unchecked {\n ++i;\n }\n }\n assetsReserves[tokenAddress] -= amountDiff;\n }\n }\n\n /// @dev Update the poolAssetsReserves upon transferring the tokens\n /// @param pool Address of the pool\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @param assetReserve Asset's reserve for the pool\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\n /// @custom:event AssetsReservesUpdated emits on success\n function updatePoolAssetsReserve(\n address pool,\n address tokenAddress,\n uint256 amount,\n uint256 assetReserve\n ) internal returns (uint256 poolAmountShare) {\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\n }\n\n /// @dev Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\n function _setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) internal {\n uint256 comptrollersLength = comptrollers.length;\n\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < comptrollersLength; ) {\n address[] memory poolAssets = assets[i];\n bool[] memory assetsValues = values[i];\n uint256 poolAssetsLength = poolAssets.length;\n\n if (poolAssetsLength != assetsValues.length) {\n revert InvalidArguments();\n }\n\n for (uint256 j; j < poolAssetsLength; ) {\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\n unchecked {\n ++j;\n }\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\n /// and transferring funds to the protocol share reserve\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return balanceDifference Amount of asset, for _privateConversion\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n function _updateAssetsState(address comptroller, address asset)\n internal\n override\n returns (uint256 balanceDifference)\n {\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 currentBalance = token.balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\n token.safeTransfer(destinationAddress, balanceDifference);\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\n\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\n IRiskFund(destinationAddress).updatePoolState(\n comptroller,\n asset,\n newDestinationBalance - previousDestinationBalance\n );\n balanceDifference = 0;\n }\n }\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n emit AssetTransferredToDestination(\n destinationAddress,\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance\n );\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @dev This function checks for the given asset is listed in core pool or not\n /// @param tokenAddress Address of the asset\n /// @return isAssetListed true if the asset is listed\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\n\n uint256 coreMarketsLength = coreMarkets.length;\n for (uint256 i; i < coreMarketsLength; ) {\n isAssetListed = (VBNB == coreMarkets[i])\n ? (tokenAddress == NATIVE_WRAPPED)\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\n\n if (isAssetListed) {\n break;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev This function checks for the given asset is listed or not\n /// @param comptroller Address of the comptroller\n /// @param asset Address of the asset\n /// @return isListed true if the asset is listed\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\n if (comptroller == CORE_POOL_COMPTROLLER) {\n isListed = isAssetListedInCore(asset);\n } else {\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\n }\n }\n\n /// @dev Get base asset address of the RiskFund\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/TokenConverter/SingleTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\n\n/// @title SingleTokenConverter\n/// @author Venus\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract SingleTokenConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the base asset token\n address public baseAsset;\n\n /// @notice Emitted when base asset is updated\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param baseAsset_ Address of the base asset\n /// @param minAmountToConvert_ Minimum amount to convert\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address baseAsset_,\n uint256 minAmountToConvert_\n ) public initializer {\n _setBaseAsset(baseAsset_);\n\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @notice Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:access Only Governance\n function setBaseAsset(address baseAsset_) external onlyOwner {\n _setBaseAsset(baseAsset_);\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address.\n /// @return balanceLeft Amount of asset, for _privateConversion\n // solhint-disable-next-line\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 balance = token.balanceOf(address(this));\n balanceLeft = balance;\n\n if (asset == baseAsset) {\n balanceLeft = 0;\n token.safeTransfer(destinationAddress, balance);\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\n }\n }\n\n /// @dev Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n /// @custom:event BaseAssetUpdated is emitted on success\n function _setBaseAsset(address baseAsset_) internal {\n ensureNonzeroAddress(baseAsset_);\n emit BaseAssetUpdated(baseAsset, baseAsset_);\n baseAsset = baseAsset_;\n }\n\n /// @dev Get base asset address\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = baseAsset;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} From 987a2874e487076318e0f4f8d5e173ab9111e2a4 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Tue, 13 Feb 2024 09:29:23 +0000 Subject: [PATCH 15/53] feat: updating deployment files --- deployments/bsctestnet.json | 4 ++-- deployments/bsctestnet_addresses.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/deployments/bsctestnet.json b/deployments/bsctestnet.json index ee2017c7..0049df39 100644 --- a/deployments/bsctestnet.json +++ b/deployments/bsctestnet.json @@ -5127,7 +5127,7 @@ ] }, "RiskFundConverter_Implementation": { - "address": "0xbF732B12f87963dF5d7c729E84E5CF3698F8d349", + "address": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", "abi": [ { "inputs": [ @@ -7584,7 +7584,7 @@ ] }, "SingleTokenConverterImp": { - "address": "0xf014C86b6071cfFB8fE39306F802770C70733a23", + "address": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", "abi": [ { "inputs": [], diff --git a/deployments/bsctestnet_addresses.json b/deployments/bsctestnet_addresses.json index a815ce37..7bdc6363 100644 --- a/deployments/bsctestnet_addresses.json +++ b/deployments/bsctestnet_addresses.json @@ -12,11 +12,11 @@ "ProtocolShareReserve_Implementation": "0x91B67df8B13a1B53a3828EAAD3f4233B55FEc26d", "ProtocolShareReserve_Proxy": "0x25c7c7D6Bf710949fD7f03364E9BA19a1b3c10E3", "RiskFundConverter": "0x32Fbf7bBbd79355B86741E3181ef8c1D9bD309Bb", - "RiskFundConverter_Implementation": "0xbF732B12f87963dF5d7c729E84E5CF3698F8d349", + "RiskFundConverter_Implementation": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", "RiskFundConverter_Proxy": "0x32Fbf7bBbd79355B86741E3181ef8c1D9bD309Bb", "RiskFundV2": "0xcA2A023FBe3be30b7187E88D7FDE1A9a4358B509", "SingleTokenConverterBeacon": "0xD2410D8B581D37c5B474CD9Ee0C15F02138AC028", - "SingleTokenConverterImp": "0xf014C86b6071cfFB8fE39306F802770C70733a23", + "SingleTokenConverterImp": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", "USDCPrimeConverter": "0x2ecEdE6989d8646c992344fF6C97c72a3f811A13", "USDTPrimeConverter": "0xf1FA230D25fC5D6CAfe87C5A6F9e1B17Bc6F194E", "XVSVaultConverter": "0x258f49254C758a0E37DAb148ADDAEA851F4b02a2", From f029174bc59d71fab87d22bc429287e2aaba738b Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Mon, 19 Feb 2024 14:45:31 -0300 Subject: [PATCH 16/53] fix: compile typechain for distribution --- package.json | 3 +-- tsconfig.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index a1ff1a1e..b4b60932 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,7 @@ "artifacts", "dist", "deployments", - "contracts", - "typechain" + "contracts" ], "keywords": [ "blockchain", diff --git a/tsconfig.json b/tsconfig.json index b68739a0..0ff17b02 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,5 +23,5 @@ }, "exclude": ["node_modules"], "files": ["./hardhat.config.ts"], - "include": ["deploy"] + "include": ["deploy", "typechain"] } From c003d5bc153202e3c56f52c315c2e5b50b6064c5 Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Tue, 20 Feb 2024 07:48:33 -0300 Subject: [PATCH 17/53] chore: update yarn.lock --- yarn.lock | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 7849875d..7e040e47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2974,7 +2974,25 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/protocol-reserve@^1.1.0, @venusprotocol/protocol-reserve@^1.2.0, @venusprotocol/protocol-reserve@workspace:.": +"@venusprotocol/protocol-reserve@npm:^1.1.0, @venusprotocol/protocol-reserve@npm:^1.2.0": + version: 1.4.0 + resolution: "@venusprotocol/protocol-reserve@npm:1.4.0" + dependencies: + "@nomiclabs/hardhat-ethers": ^2.2.3 + "@openzeppelin/contracts": ^4.8.3 + "@openzeppelin/contracts-upgradeable": ^4.8.3 + "@openzeppelin/hardhat-upgrades": ^1.21.0 + "@solidity-parser/parser": ^0.13.2 + "@venusprotocol/isolated-pools": ^2.3.0 + "@venusprotocol/solidity-utilities": ^1.3.0 + ethers: ^5.7.0 + hardhat-deploy: ^0.11.14 + module-alias: ^2.2.2 + checksum: 6b9bc35ac7cdb2d828312c9ebcba1c55e3b63d6d8d237affa7b5baf94b5c2a86e296552c153a5c077f9b6178cc73c7fd20804126509a8a8670c5b50eeae41d2d + languageName: node + linkType: hard + +"@venusprotocol/protocol-reserve@workspace:.": version: 0.0.0-use.local resolution: "@venusprotocol/protocol-reserve@workspace:." dependencies: From a3bd0b8e5073410adbc426034cd6cf42a6043e5e Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Tue, 20 Feb 2024 19:17:13 +0530 Subject: [PATCH 18/53] fix: spelling --- tests/fork/SingleTokenConverter.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts index 3b5ff7ab..4aa3fa16 100644 --- a/tests/fork/SingleTokenConverter.ts +++ b/tests/fork/SingleTokenConverter.ts @@ -52,8 +52,6 @@ const CORE_POOL = "0xfd36e2c2a6789db23113685031d7f16329158384"; const USDT = "0x55d398326f99059fF775485246999027B3197955"; const BTCB = "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c"; -const USDT_HOLDER = "0xf89d7b9c864f589bbF53a82105107622B35EaA40"; - async function getToken(tokenAddress) { const token = await hre.ethers.getContractAt("MockToken", tokenAddress); return token; @@ -108,7 +106,7 @@ forking(35936683, () => { .upgrade(RISK_FUND_CONVERTER_PROXY, riskFundConverterImplementation.address); }); - it("Succes for core pool through PROTOCOL_SHARE_RESERVE", async () => { + it("Success for core pool through PROTOCOL_SHARE_RESERVE", async () => { await protocolShareReserve.releaseFunds(CORE_POOL, [BTCB]); }); From ba39ce060d0716be1131913e4dd6e93c1444e0c3 Mon Sep 17 00:00:00 2001 From: Jesus Lanchas Date: Tue, 20 Feb 2024 19:46:38 +0100 Subject: [PATCH 19/53] docs: add extra audit reports for private conversions --- ...081_privateConversions_certik_20240215.pdf | Bin 0 -> 1128999 bytes ...ivateConversions_openzeppelin_20240220.pdf | Bin 0 -> 229252 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 audits/081_privateConversions_certik_20240215.pdf create mode 100644 audits/082_privateConversions_openzeppelin_20240220.pdf diff --git a/audits/081_privateConversions_certik_20240215.pdf b/audits/081_privateConversions_certik_20240215.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ab3d5049df5576b47c992801c0b6a3284e70a86c GIT binary patch literal 1128999 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 z%0A+{&&PtCG97((oi}*b*)(PILIb$WgoK24?slzyD94fI($5gn9y5hkeW0bIaFoUm zm%#o|nTS){!x~y&h|W7s$CKGMU{isgl5B~icRRXo_@^=Gu7=8)`Z|%YXZp^ z)x)k7L69rz*CtDV6kX_q!LlGvi98RMP{i^G7O}{;RaOtP{PilDKG-1wRQ9%-$BmwD5z)jbBlng{V zb|GK>d|}n7rsgT7A9vp%F=?em^OD~nypu!e`nw8RAwIkY#yjp=b|k^jediVtbPA$O zfNB&lKDYG(_^85wz_KcY)ak@AU``Bdi3iH$VVU()s`Q*?`&+{@iVCZDvdvc!Gx@^q zpygpL1{wro|-7XqdbnruU_Qv6d013A~WJfh;cpgmw)!3qw8x((phArLD% z?p2OGEzQ9_DC0jhc@;4X2>;b)JwL{}Y(aE3C5mIXzS5}dBHz2_u$Q3b5FF_5&2uhi z6lR4NHpDYyQP7*4z1a_?MHBW$-&j47IX1LoT}y90*TuC5#)2J3UyC2zDJ+Y)>2Gvc zN!1g~XWN}ewGcMSv8!8p5+JEAFzEuEk1lhG8HjIzh7I>ppS9JqpnG8)RCv3(dh1rdBFZ)g11bpA7=$ zZg_n9*i^cgv!;JF$DAXH&Cr~cigxhXh4w#d+fCcNo8jz?_t9|^_YDo|erbxVANy+; z=}0esdw6x>N&hp?aunS-Y=Y%^Fxi=;`EJYf#-QyhlaV(P85o&e&YGvkn4?{t{DCW=IB)Y zkszT);%JHH40mxYeQwPse@UkAhL%6UmL1b|<=7*s{!rDLvbVpf_gA4Wl}c9!{qpiU z=u!%mZ95fR+Tx%zn=Rqf{i=p1*Ta)z-{rhPQ5X&7f|lg7}}I<*B=$9k-}+ zdQT7rdBpJYlIQGeeP~)WMT%hQf^n!2qS({+bZ~L8N5at$&KFC4SZHeq+wiq}dWwf% zU^VzaH&s^iKfD}jitEmse>qgYega7s9N)_g4(N_NTdK?wn8=FAOaFQ}rAdBbCQtyi zbV?gmQ-P1IZA1j+ZiD7wGuxg*D2;iArl({g=fk{?2HbB5!)c?J9Kz5xGLv?PH9>>B zop%yDGnU5w;<-V%EDqu(DO5^a468SQMlKFE&UkU=0lCl1#?S=e)ZV-XlUmIz`W z6MGyGjUrJx9 zm03MIowN*PQ*`R&sD{DDiloVnx|wqzygxFnD*DqKj>J z0rr~7QJEe`A=h|e*2B$VjHe~|fgp;N3AdDWP&4NH$BgXpliMoI$j+qW{y}rlAFlBr z+qV_sc#AG;`odELY76x8U-HC6&_QtO&OiwojHFaUYFJV3K#tgghW;C>JOc($@uW+v z5G4xLumQqoc+nUfX%lnULeQX@q@>ms8(8h;~lWD5bm+6}qDKu~k0%!GnD>>J+ej z+h2X=5?xeiYKqr4!j5}t0uLL2G2_9)m!7pYr0*nN8xePyZHCZ1jnIq=K_%j<)~JhE zR~+mb{V`Q=-jpbtM0r^xTxHIdc)-bMG1gQXgG(l2ilj3$M!IydBC92bqY!rshyE+9 zXwcF#0e$tR$tMZ!m=)4fM)Ok)$mEa*9>YtQ<3?kv&sp|-B$b}3f{2c}Um?#rDHZ4V z9qjSf==^fxUiLzz|6dowz?LcA@)FFe#DTWJh#$zcCpB(oy^Ii;^MPRXHo!c$Sm%)? zMwhO0q(Em;6)AUpm@FUuXX&m5`nTepewL`=;cTEl6lG`<2|W0mQOH6%7l zhbhdMk9@+Cw9$$5<9rh=D$Hc~8&4xh*Hb zvHQHWlQ1?Hh}*w|<*NWB8be|0XOJUyjF9&gC-dY)~ z3toZ&vL3PS5Gv4&lZ#yr1se8J$@Lbf z8ibhu$q|AQpykE{$c!e87+|=(8qb9;<>0xfF`&!``lh+I(+>w%EFVsHXqRMd_6Nq+ zKqT96%js%vj$9}d^jknZ=|mIU)SU&XG~o16QdPg2{n}MSeBNIA&T;ejHmuQpIKYg$ zZ@#cEO0i_iHI8I7q;1B;(IsPsTk^Gkaef= zQ(;i4J?T7K@_p_GQ)5o~0}DWYd`!%&oSg2Rhgp%!2*s6DFiShs1@Kk)J*qEspy&e$Q0TfBVE6YEnn3Q&0Sx zm^K%(ehrr|Cl$xCmtUL4%dCV45n^7Jw7G!Wl%_qY6Ha9vV6+g5()?;UMmXc zKaySJ>D*YsIr0cy1J#s4<{%(CG5~bStZmx@M`B^F9)q&LN?%+nJOifV%a#Fdp0M59 zVAafkHhAq*MG$UBFvC6=XPSHvN9tyFtSbGARMl7$E}4?C8IP{n5kF=LnvSwAmxRTag+llLZdYE_z|XTnpF;VPcF7`Y>wX-wVKZi+zmz)E_ea@+d)m&9DU~1 z^Lj!9ea{^_`V-WMLJ720-tc#yBO#JEAKDwJbSSLOjgQ+eZe$vMc)92=8}A=kTluGd z>=LBC;^A2K;7^d<%7lWPV(OA1;TsXt6{7~_C=#ZoCH5W#!2SlOJ5&n!weAzs#i>Pj4UnT>b>Vbyy36NnLoIq^&n zl+e#1Ueem(VwD{@ae}DBv9|TAoDaG8?sEcOZJXHp+mgCIt=+ISZuPHSMN96vD|xcC zhSCa{eX(Vg?K_9QcV(AGU)2K;Tbbinfu7koIsh@9;QGz?1~>FGKp!?*8X^Pk60em& zkqKC9Pcr<1FGGWUe~20zFP(Gsfm~}H=f+7Hkb8*^(^4eU2vQppasPV-ZY=>-}J~F&eTEO;2#dSdug+flhhPEC>~R$8Z;i zDk2Jnc7n6};h=LM$P}TPE^U-!>cohzif_Be4k-&UJ4mUUXNzN;=EskYRV|G@;$6HS zuAKZx*i2xjVO*Mtk>$_)b3bZCyH^qe9@Uz4@-M)5o(91dk0D)0xE#>8Q;~>pgj7PI z^E9Z3VbumK^3Q+fTwj7}EDiLeU(RDT;P2RH7*d+0!?UQVp zU`CRWLQf6}nfZ_ExP`lq5XQ=b+!}+MI2D#A&p5)PW zu8Yjv^TzPx)kQX^sVZ*b4USvO*M0 zf2Y!q(AkSTQ}Lc5yo)beU`?0!K-YA+Xgpj6cp1Z&aq&J-YzE|6l+!$2TYV0*8<)S_ zg9N8n>bmGS@D!;RAPNV#1%NQAK@kI|lf$azNMSOTo30B=j!{RjEw=!-H1sUg{ zr#?MYmG2z$obSxe4$YBy@=v5!w0u}u!tS2CuhIMpK522(cljMUI?Ea52frYLS_K;Q zP9hJd(wu$>UA~4|T;tzam%bANZAprO9@O3&gR60)PHcMc7O61+>75i-qZ`HTyka9(kFc7UMx*TPgOQaS(a6}p> zpRX<-8&n`^fSM0)_=iNjAD=sQ(`xN|;)gud7#)`YR4k95N?hNP+ttQ0@CV9#-FEf& z|2}DGvi~K%T_ig7z$O2y^OKVW;x9#_eJ!JH-qFv_z+(2v#>K_hxsSZ7=BpK!cZhQt zXO}Xb7oB>**9CTU=K_s$9n%WT@c`oTlOgVa{f&uKV)UB|PEIVlpRVJlClWuq`a^Uj zsGk_PY&}wJx+%*{mg+uqu<>bakX0a_rIm_qz%A88g~zBiH`E57nEZuBe%F+zUJ*RS z%^m7pwoW(axZ+x=++Bkc$>u0gis;1Vq6e8bv83&sMm4yBwRkL7se<;LeSz63#|$vk zYkepm$`}yU626_VxL*j2wSBl2a%&Fu8vA$Gk(F56Q5P^4g(~O&#$KVZY|3Xzi>+Sl zGmp@kr3;Y~G?EfH)fczX6}0EyIpOLr?30JLyw4#==b=3uf=}Y*u%Js(ZzQwZP=A60)d{iR2eMGtHO%xs%-dh#g5>H_&KtrMF8Fb-0(_ZbF8?5d0zn@+#EZqzlB zXLquDMP>V#BX|q7?{P^wn;9VrsfdD=oHFV~4NVhJj_V68(1HoP+!!4E# zh6dwK{HMWKj5T#Y6#e!5;!96L37H|uB4~q$aRc0a>a6MN9H23e7?FW~P-tZgg{rRp zje#B)hrj<588~?FpZzaYDv^F0#}a!gMIK{~a=F!toQ68b8u|?z2%9E#*^;9=9k^z? zUVfCMP--z!yFj4`&?#1T=(85WtEhB1y|x6#G&jpDEI-=C_7e$Rr;f0z;yAYD zE+4^#BA?1ju)kAr=Pw$Kprz?4EB1p;esG4ni%8avZSdOyYfy#-Bz*=D4gT~hV-cA(UCK9+s3&27N1cB&zZ+Ks>%R+bQ#H3 zid-rt1Nqq8zO!ZiWFJ{D$c*ZRoVkLes_OYSx~8Dg7*I+e>L+E-KNN04b*`FpTHD!(F0qetqNh`x1$5Z&Oxc7_< z4d9Umx!~IOEe^it)@7Gk=x-nFZJVCZA9UPzqm9h&+EtVuD=0t2so#-#2Wvm;GdgR_ zEj&OSe4})cDVqXiFzbF7SyufH))qY5j{Y0zlmgCi#9tluumtD7%)>n`2PomqYomSH zpI&dRT%Z--JYH(IgyxxQ4b%|(e?O_Z*<xLEyAGT>pWo+Z}kS*p`;<(;A;;WUv>@}mxomfq#CBP zdzgG9NRiGDgU-o!b*{E;myr0P8+wZKK|ELqKw{0-<7omK63&u8Hc6I9A>4K#F82=# z5~Fj6_Dosh7H4Z0G?ZCSDL|~xj8}~eXm2s4glp6zLNf5Z)2e)|y}>_QUTY##80QV% z-z8%^sM#E5g0VpUCVv}NBn_N0Zmux4U3gd$nX2=qYo*jLa`UnL;I_H;mZfRQyzyN{ zYaj01ENy384$6XGSL{WVBX0Xx4bjHM7G@6zf$pU)Z=v3%jrW=*oOr8?-b{PZAabrL zyzOVe@4nCoTS88qo^07BG`)}Z!wnpW`Vf2=$A$fIB7dMOa@E5VSA<@VvAvjt$iZ7g z4*vBsFSc{Zbg5IsgniTtwA}F-t65uNfN{kk?R&Z$Nj2CKbBr}x#&ws5J<@V|)z%TC z-ac-Q$`)yO3GTGsBrh|jw(zk&YS7(+2j;uRF#8JAjRhq;MB^_`E{)MNvmd5Q2-_Mo z)Y1(^YRo8Se7ct0QG4AGv5H>Ydc^Rx$PTU@IZsDo-@W}2Z~DxS(u`0 zu!@^coV;`mG07PzAZVY*a9u$TRH?ZkL$%=&$QJq?0QI*PLG3V4;nf75(+2q2ae{Hh znroEoHR*shAn9P-$Bl7*7I4$I+9k`_FAYQUU9qc?tE2Hi#$hC+PTwdYL438n#O`WL zFcD8gBw*rwp zMYEw#n!4`t{js1l2K%?my7YS0!{5PO=aOcO-~$4SMOL;^Alc}7aS`ZH)qbUN{c6M9 zz!1;#irp#}rrnBRVz7L1&_QofWog>Z#8FA}tcQz?}S2B|j1ists5w<_+KHxed}O(%;*1fc#XnG@Z;Y#U|Yb7))&bayBxB^eCdg z9LTcV(OvAjuUMRcJ8nPIj<&MBYZ>U--w3}?Z^$rcsCCs0=Fll#b5l)G*fetH4ogJ4 zQ^pANLOp1%*@GbiHi#gI**8RU=@!r%p8WY#^dO3ZCOT&^a1OTS(>zAO`a zZEMG63MwY|+l}tpIG$pGt*qlvY|o6F?LsNPTF7qj27@1Ees5qDibo+#Y>adr|aw9&k0XLeVmCj6Q8&Lyzd3@;Qea z&jQqCF~O!tdO5Pn+|@I1yHtjgMCa=X{rvUN&dKD*x|X|9)S^OJ^o}ASi`jvc$xKF0 zBLg8Q1?+${KsE}f7G=5Q-~Z8qrx~0E8+a0r$!1CK&}6;sS)H|o$~qA4_t`>|?mW%h8L_Q^=_`-$AO6Ar zhsPs}RX%NK&QP`TIX<>A4At6s;So+vf#%Nam^~8m~D;| zU3Tokp3Qw3gg1BLrXaA|iDSQd4ol<7mrc{Bqjc`j?4jw0f6wy zM6`KbhpZ_V1~Oihiy@|P_)2n+%DZ?-G)`2)f0XaR(j}=yWZawuOv<_Rqj{bMZ~gC zLCFQ1JzlxOj?GI8eW4jmsI!4Wd+bKYaK3sH8971u}XX=GJT)~5rUR)xT zumhRkXn~GFR<0n8PzEhHzzox3VT%r({N@W@KX{Tkc3jxP<=F!8Njx`u6fi=%dh@CEC^%@Oh*Ggi`m9=5VlZYL?kK7YdNgEBfzB=3+&5z&DRU69sfqLAuzAEs4r{D8HAc)537y zjvI7KRAUy{jE>QsUm4dL%Z|%iIHWylWr(^N()|zj*~eZm`qxsBL(DAY%g~lZqJkh0 zC>0Z{K`;O`JqOb40LUc}#6WbStq^Sv5ThzNeF$r0s%{^5OGwA7fHQ zDYnIaSwsY2DKPGgzDp5N!1Tr=MPZ76mQ{N)J?qcnAe%pn-jWGL(6|ay*ztS1?ds?fr z*7p`xR@w}^#~8Hr$IGAEY0mjHg-*jY?U0>IO53kVh+ZxAE&42S6Q5Vp7KeNbD>!xw zFO{5I9x7_$Yy%g4*>P1(0}(ha?lGjrJ(+V)h-tzG{=` z7(?>GQtm&jEKQcQi7gapLE^okqc^j9BUd#rP;JSyc!z*Fn;1JKh1Bb)zaZ7EDZqbB z!Lpc8v8nwqwYLOkdJ3h-)%3>-%K{ZqpRwab(IcChm-`9im_9x;Wuv^kGvv!<#Ux9<1)IysX>)ajR$*Sava$;pk|G@Im+@B(~%PjeSQ_i z135cNn|Hc^QFfddw-4+}9My0o+YvHY_Fh&y`>pHQ8kYxKE(0PhaP6IEgN-P>(ME)A zvf)IHs>C}SR8SAMY2R=ynQ4=gThg~OAGGWNDTOq~?5 ztv%wddXOo+rc%2MtHUfM(mN4%x?@RDC`dY$VHLYNG;N7k?};$Y086SVt5l8?8#42> zDNEoPohFFwYtoiQfpo&IDQXlj`@$pDycorLd2dPnZm)`YOta3i1+n%J^)uG9ItNSI zPxa{XPs+N)VHVg47Kh>--S~a>#;fm$=gMk16QZMepgvvfj#X>ljJXZ7tZ;nd3`@Mz)C zK#(yh`hsc<3OAs54jMJ(ouVU+Dko%GdC6_O9AGGtzA%9*MbbqXOVQq9DScMogzmm5 zODOM06og3VjGoOg*2)`hYnI?e3-_gKw4W?|^>VO`rM{A5yC>a#QZzF$r8*IK>GfQ! z0O`|3Xrqzl<5i>JGbvU>|12N1E<}cRP2^(0bbgX+EM0 z&`3)=7ie+k(JiSva2z7ASS1AqB@y*6?!OI8Ng-t}PpSikhy(~EBvfhd%2X z-A)14x(CfC+Osa0LgdS;vP{?NgQH-{U{7FmC2w%fqhr3lMXsRb^k|}*E=Y4lIZx2^HgT82HvoP{Xzcxyw>?lLX74cNR0LeeSVB6P>Vr7 z0Dgz{oau;1TC~Ny5080QjaG}??Wme86{K9>NrBbkW>A`IFLMB-NbuPNSUWzP=j?H%74M)4r**4? z&e%=t=2PE0W5*!FP?X2^JkJV9^17c3tVoEdN`%tuA#@qv7v@bOS%;fW+^lLZqt|2A zU&MM4=hig8cx*eXMjLc45%z!YJBcr=?b?TU2uE8e#sb`qlVguBCZ-Y>%RTcPrq-f3 zTUmsX9_HZP9wwrr{k+>7kQa-tRG$~txwAq6;?s@SEFB@<391?HTOmNmlvHD_%1^0e zK*v~L-*9bhiII^rULKiNMBKT#(Sg9Zlj+3mmQz7f`bxo5`YFd*-mqS7s-zMw*Fsno zZblKYdvP0u4$kn`?yNo*s$k7r5UlmQT!Nmf&`g6n}AMHH$y=u(PrwIe+V$dSlK+Cdnlz1K{2)T-VfD-$z?_%Uh3pHaE1sY`;7c8$wB$ z8*cnv-gkX9a(@(cwS3)ezBxAVS7)z%{#T{^Wwg6F?Cu>;FTX>(Rf->DxYC9@>pbid z%QwUhB|wD)xHi8U?aI=j+hg2I#9EE>i`SyZXPm=~R+qXMty*B64gB6NE|`i(+Bsqp zkC-Yfv=m)lZ1Bu+D7J-4&5*iyBhQ{$iGdc1VtK0@gRUhJ;ey^fh$U=6N`XBB%(zwl zqS!+$_W1orvK09#ZSL#v;LXqBqx1-#r6nS8=8G?D=qf6?xB5o?tcfy~sOO_2=b~kT z(Kyv!6st*wI?&Sx(iejHcd|t_C|02iQs(uHb06wCsA%3^YC3XSV2@QG3e5%^ey7?Q zBa@kn51;k>t-k`r^AqJe1!bpNKE7SQG-KOeq*vZFr8=WK=bmAC=Kj^; z(=}D^PiyQCXgYuJRPKhVt=o+c_7(?`YUx4BA6C|TmId#Hd3eyi_H1$QhFR+=Y9MCDjW`4fE0LkwDav8J^1_`BN`J0dm2g6pP2OOa~ zFOBsIK8~GhW$d=2-d>YPr{R~^UeGB8ysD8Gw6@jLbV>q`o@Es)Y<@K`{>c_PLnq&{ zMf=&l;_heI90hC6aPNuySvJ9bMdn=L}kFDo%!Lk-;^WwoXJH{Ax2V_MNEIa<@MXMcS=9P52lyf*|Q(-{8sjx{A zx6{)7AHYH`W;D$_#%q>bJgeAJ)VuJ-Ck?2n)f>Uu$=9bVCm=6eSUKw*!={fBvmfGC zPwe3|9xh|d1i8WrmoyI~`d#RL@p{beTmPq`@}}tE*|}Bja{JPWAh)a4OOdkY8oqDD ztzAJiovd(|J2Ii0SQdKN+4&oyRi~#W~frd zl7)hq-h;@@PIlfzarAY|e7+NICNmAFx8wKZW-GJ0{A#t2vYY}s0RC5|TiT!d>fik{ z$atAfiQ;a1U>@U}Jz+_Uk}SIBT_I~ubsSHU!}^tu^Qk8jD9~0U?!Oz<*cy6G@*Dkt<|g6d_(7j9o@B3ZYI2S$N%{??Nxw=I6g zpWQ9B-`TJH%H62qr%xR_o$3<-m>N7gT;CE@V+U0ryF&czZgfF!LOa zr3jwI(M=>8z~oX zk6KX}MtY^~c%^x+hB^_dd7!h#KuNrtE9~nDOPa{|8|;8)+l8C#Mlzv_BpkTFY7RX^ zU1Wuxf#W+3s`3uyu(TE#xvUPFy*Bk8FxH>L>rXb^$l@a{)j|5(REUew&lR;ziF8Fd zfx!Fb`JufSv@D>oYW@EUon1a{>Cmq9(DTA~?yNY&U#RG8E6$5WN=fGX=4{tyhAB%k zfFUqR!s#?QKB8M>;vCRDSJtwf6yW9%`=hKbQ)}VfS~|rPH)fh<I zt6ur@$hR}HA9aBTK_mSNatptqHoQ8qF`q9OS-Uy2ReivI>u$HMmGO{NhE04JZ$vLI zePeANQG0Q6%5^&8*_P2k{8gD%OvXcK_|;y6ZO#;`Mu=a7(=Er^u7D59W6nvoo20l9 zTt<0fCB^;~EWSYHKyO1u5yccgu$3Wh_=4BAqo%QDM*y=DtAm2hzRjXAL4LUnl+yWb zdcMXE>S`L8*(kFZt!fM*YWx8>%X~pUlZrkH1oMm!qWpkgSys+G916BvhyJsL|7rHv zC0)boN~A+an|s2FE4erx(e=qDeHct(5niEn;qfZeu7N%B5g*Gjfa zq4T!jQ=Ucb?}#x79~l~Xp-EA2Q+soq_Lt9ww2N1%zqyDndc1Vr>@>iz_j%ht^2^PO z*5xlvesNzWhhWd++)2tPw)`W=Ls@+1sw83mI|>wRRnHSJ&d3QT@kwbc`hB#kwa=b7 z8HVm!$GgLEmv(0e!!O`WlY|>Lv0na(JCKBy16+#8xfryw@Xjst7S@@V@j~p#A!yQ! zm$4TA!=wCv_ObIya+1~Ru#@|V3hToK!WBc8yHmD9K8>AatDn5!o3Xht*qrYRb zT}GHnQQAT%t?2t!((d-gh;!Ll6A%+;33xla-7ylVh&L_QeOS1b>FT)8^}&9E?7ytP z4dhMi6E3S`j+#h*u?(8~^4MV4t2~)W%L?seHOzw7y;p~ZICmD@{f#_!l~^pIbzNqk z?)$@9CG$R&yEYv&v`F1Rh$PviW;}S@D%5p<@}S1?n`1Dcv|;cV!CkEwbfki!vI*$M zw)#TobmMv`3jBEI+#G(ma2W7J)6h!z|Hago|3mdh|FLe}G@++}AnJ?Hv0l zU9xl@*KT`iD#G4?>0+}Iu$M$kMfCug?WrJtDUvCW4(dq~w|t;@N)DXZp{r12LuF$T zYoy73G7yErpfguX)czgbeqrW5FR3)IGg&56D0~jiLq(<*xLR)^iN`M0{ry7miOC<_ zuvLG*o-d7Go>r?1S^&Gm4jZC0+-@V7qFX!<@dE}r;{P<<(D>pcWurXWX-TMD$$$m3 z-+&~&FHts`YlYnDZM|0i&7-$_n<+9EhuR@ugDh|aDo3KX6Ih90xN7B<38NKh^{U-K zSWM5Kfik?NRH&(LWYNf1@9a7 zNGnQ418`=PZqCeHsFrwtYKW}*ym|BJ13rcK_SkgG4Ecn7(zmPC6Pg`OiJd$lM>w76 zX9V7UxRF>?MsEGHAAfH=k1?mbz$e4u+%VPYy zhh87?vo|1J$26E zW~*?MGY-evnyeRZ2wgOKO*GKNI+>2ySUS{CMu>_`#m3^=p9q_8sJ`j9>oy7-9bK$4_?hqPlYEKVOkD3Xis=U`H%S z4r@hsxFN`^FeHk8vcG~)iQZ1Mw~fK{yfD`x!R7^ZWWC6OlIXd4g3>y^S7gYfr(|sV zXuMLNrSKz}q)Y8jx-~n~K+`%;1(u z{|M>Up5kZ*?g=~y*QqxFA=ECM+7CyT2ZsmRM+3-Dfj0pD`vwR>h`l?=CkJq@6ZYH7 zkWM^sw9yhctb^zzu)yCuFF`+aU_#F^{hQ4AxR_BMSqf3Bw{Q$L_A^p$i&aR$FK64V`K1pge+nm!z+GL{0ci(xig$?251Qh5DU?{Gq)W z)6OI0Hj}W?r23}WgTXtiF7Go!7d9^E{4jrhe>eWMRa~s?+M-v)n_)TpNrNvDk{gmk z1{o6hIChqAluMRP2MU9$@b~aNg~x7*SGBI2*X3ill`wr6`Y1dP$3rP4ZR4O<_fV5e zo(V~So|0|!8JcRo>(o3X+Cfz2H$q^yBl*8p&xK99Hn1=0)x~W)u5Ss8;JJWZfk?0g zXfSg*k2wIX>NX4&oZkh%FA&37{~M1!Wh-*U$;uuU2oliXO#y=;7|0ENKdxRCDkFhH zLtF&{@61}itS`p`bAG_WuCQf|GZ`#OT0S}1(xp~L?D$hdJcM+Vf=rU6p^yaJp>fA=qr0;XJ9by@EJ>6vA^K_^R!;PnttrWLTr+?IfnTIX;zsY*M!%G0N-^s9rfDq3J04hR| zMuU-^O725#AS!dYf8C)okc)H(Ijsx*?y6fqg{+7Myru{5`2mRo<+i}2Zwfe=hz+I} z3o~`@{IH|yFh&nquYFldP1z;iE67?SEFl)})lCw-BDeQv5&c-J{NYINtgjEtjp=h2)_a_NRy63T z6)AJpCj4<~i}jagfrZTdHmC0i%%=U&E-Z2id`8mH?5hSATQPSl{Ouft3ZWAecssZL z3o4*^sFIFJZGT*~AZF#K*G-v-pkW5yv@?1h6xT4o>>M(pfm!m$Y`hiXNM#sYHcS1T z{TftQnmkX7djN!nNZ$nfO|cAm$G<8fJyRv=)Lmbd}C}xFz9LbmMDGJz!j!?$it8z_aj^$kfrCM z1D~rIFA@}1W%Nr7g{6DSc5a~AbW8dD%$OsGIGV1inOS)}q80ZK6$l}A0!0_JmH7Np zI@jH`z}crLx15iz)#9R>YFWjlylc7TBlQGP1EGB-#^k( zl(8B4aN^8x3G33gw!kb6*1d0dlc2l7o~(=rWuI!fIClAZ8S#OSZGjo%oAj492QRth z>nN35YPsD(%AEO(P(tW82b-IHDev0BrW`kRJRxza@bl0Z+uG5)O$g?|2bKLk=J-ML z<3mA1whg)0=|*VEH-&Fx&~`nZVO_htfVB&c*P?udq^G?pFHOd8hVv8~Vko4<&qK~G zQkZLyI#LB9!mP5aZ($6{3iYjR-TCQxAQp9u4lgyG$c3K+?kBmALjIhqJZ+EtU&X?Y zv6DF|ngeKPSTHo~d+}QfhGCsxriumDfb>>kJg6fTHBArp+O|`#FE~#M@n6_=__TR6 zP{>h7yp-6%YrvuneRo$+6~>IB^9@`h1ficSkiq8Htbvk(xflLt9e2p*l{64gY!|a* zRdvgMC8O`b_u5P@-P4I%_4joLFjlyr(N3@T_sj2Zt?KU=`)KOI5+_kxeCY6n%kn-& zOs@E^W^6@XD7KE5r!%sqle*)bp2@dczr&5_$BcEZJe9=7W*AVuC zPy0K)Uo5p3hRe8OZv5OSf0=ez+FbK<(AEQUao78HBQ4EG+zH#=;{6ZtZAY9=6mD13 zpL7)01TTCT_*~3kjG+|PWR_A`Dj4RFvX%ixGDTu;d%N=eLR`35v>_=Ssy9E$01O<@ z(;CEDz&;|pp63b#>g(|0xeB@!Fc;T3lMwg8g60KgH!sG&grAe5LE^=G5;$TRQpMxjIC;|bdc~GCHO`^!rxJKq z9@0K!t{8@#v{gt$a<9#wLo>#-GI5ne^`-OceUi|UJ`2Q!0JKSO1(|-xgc^r<8h0eI ze%E}i#{faJ+9A)JJBv>s#A^>czZ;07bh~utU5l$Ra7T|Q)jmb*z9{p0A90d-Fn{p@ zdmz;_Lm%X*y*w1{)%+6mEA`lUInFyqR?a9}5rXKse4>j9tEAN}8@pSr*^>qmdy@P^ zPgHE)hP%HCJQ2f?Y|=3MCU0@cmgSyhv;^rEs=d{bo%?-SDxotc1Yvo1>{pI?an@lg z{GUS=_r|S?1>dCIC_yDXUOnuogjrJ&en?RX@YL%+RYd9k4Bf{!&h^)r?LMCY6{i~_ zOz5V2YMRF*zoWXRpK6FUBL$M$6fsJzbO2#*51EK?+fe-Q|k)ut1-M72+IP5iSG8J|CebQXEtxQ1v zfAvSlR$sdHHWVysniAc9a1>7}d9|IjbmVdK_>g~0t`C2Pnsv4xA!>QG(mT|=hP$Dz zk+FBP*rJI+S<8Iv#h&vJq3Urk#|5f!Kk#@z5IL2ti|NV3jEBGkp(!-H$(tgfylyeL zx^C2GD1S$aK6%%W!n)f1>utV|0A^!#-wdFfoun{#rRv0#k(NK;TR8*g9bB%wipP)k0<$h^ky@%JQ*C zkhGy|^*rZE8Dh*Qvjc>z{+D8KF>WLGCq}>q4#)2mKVUOxrPH=9FoIZ*{h(H;Z(A0# z_P})k1rk*gQ4&P>fQhvebw{jHM*G#M&<}UB+s4XAsa+EH(E(RK6Opvg0gO8SN8ZM{ zP~P@nQ0zI!3Ffc)hEHQ{U$S+M$hYJ5iZrB5%eyl=dr9Zu(Dwd>zI!?%HStLa-nU$g zvJZ$`1vm#5E1mZ?|7qZC*1@E)+!X``^I8`s`;3om&?-14kJw$Ia%mzk0 zZ+1c+QTr~*eEuVN9ZliLW~3F9dCl_XlXpW^%<~cHpk-=n(=N;!cn&8a4nm3W;^$j< zWO(t?_3~h>Er7RVq;!+_R4ZlF3ee-nxHVzGBoF-um`oI#@xw9t3{grlZ_1F0lLez; znM&ILpvzy@2i<3sstVT~2((~b9Ew4FtOxh`skfIPIUO`M0esZqJ#Pc+vw1Y_WLnBx zGU(r9XPyA_;*H~2z0krj1+RvznA!0ivO^#)k#I@)Gb_`>*_F`sCM!`*tmu#bucspKmIcNaXvfelYDX)+G{Ti-NLi)8*EnayXB5lr_a6f-PcDujTy*a z%{He*nD`}yB0fP6=1p=b3aPD|V7}%+8ki!hvWGMD`+PXO+8A*ak}cfDAz@yv?)|LQ zBHzHRW@k))252D4sL{zHL)CJP;*B*a*0mN~L<^LP zW!y#&o%$k%JpU{`exxX%=0@^9Vdhq*9sl3o4EEs%QF8I+-EJNJs=MEMV|n~Po|`?9 z{)tC74Cu2?tBQL^amB{v`tC7&|I|?oSm5xFyxI!>D-2Hln!H7(CG>UJ*Di*5TQDpR zTQC$ks{xk+nuK{KD;{{YcTr`TCS^1P`Jr!k*7hg|FOvp<_M3^p%$Ir;p^2J6ua- zy^fdOe&YZ)sirmi%_*JcN?hj+a_e#Q>C;n)2Tya~9uhw5ie{=;OM9Wc-ZQzTyJcI9 zT^_&6>F(2Y4lS1u?4CH2^E&Lh?XcXyo_|$mj(C?)&du792Me$KpFdjj*A1>E><*|Y zf2w=>aBcdf?Bppnd-dzj%k{$Rf0>2Tc|JyaD%<4io#m5KTb{U>dvKv={(ecI;uDX^ zxP1qziWd{k`361pkO3rd@6zIg$d>n=pSzESif=l5c!7>nsEm)42V*33_|%M#{B$l@)o7|f>HV@v%=bG$C5${-$9 zvU8WvwGD2R3#V`U$ij>EVu4@e!!2ZG>58a)L1Xz;B&nvm!BiGgd0mZzV)J`}(@fv5 z@=Z^iJca%4d3sc_I~d-ifbfQs&@A+iZ&`c&#vE8Jy+paro z_0jzuL#DQqA`Q)$$)tC%IJs^N_^BJ?^0It{Vb#$c*9D7a#w-x6*$$`d%ph{08QrYY zU1~`Ku!&9*6n93Z+6Jdwj;k4!gltMTE41z{JiqV^tzJ@)fLkI+#??rvA_npU{%XQ| z1Kzm)%;viB=}}b~?e?@}Z|T3O3gdr#2A`uw9|>v;xZdF4-j4Czlb%#Z_OVq*0a?l! zMApD6aMT8{}A9V@7t|fUH=khCK_h9I92r?=AfV{UeQTm?e8^!(6s1DXc zW=kbej0?m9=E)D+WjxVm%!+oOE`B)IbnueIrJ{*XFSsOXZtXUfR0chrH*Zk7XefE0 z!D{HY)lKh;++kQio}nH#C^*baiK1BxH_alioVxtP2f-nB*!%^>@a&Z_^XfrF=6)jP z@uG7fW?TtQ+9a4&Pw}sr4b&80^|RR&&A?uw8~u;#aW0iXNroPb%KQX+k1*lgv-9iS zA{dWa`!uFp@$`E*2A(f#+efx>+&X8S>T!*-o}_>{wpEvHj;@Xk>l6EeKv{%=jB+cSGR%kfBSRChK(?jOxDK=yw4&w8Ui8@WSE9EnN&-kZ8P`f$OEh0` z2nT278ZI-x4*l@1Q}Hj(+CY04y;da95OsPV34DNO^^d&kIigmy?q*87US6PP4AA*I z={Z?RLc7;A%lMDf1WSwGDH$_4K4CGBkUVTbj)o>p`jLue2(Nx6Rq+_5^S1LlwF`5C zUc7UcZBH*cK(8W|qVDz@KT{=eTtqx9Ku&cFC4tXR8c9ROV`~ z+o~0Rm`md9ee0*0mkM%24p&&6x5b`}@ZokFY$}J(_6aq$KsQ*6hBrhc=(Qbp8kNS( z+rR0o_Fd?<))~4ec8aoZm^}|H#o)hF9-!%J+8Fj{rb^)Wb^IFi79;$kUut_rmR?~f zhaUk`KWB>we$ z^u9_cI>XIr=oP@%ocUPW5!>pV$EgFLtk{KnCCm(7d8sD-5SBmwrXZ*{ zjNUrJ)|$$0;G-01pBE|2a)#Hf-TC3;Kd#OJZZ}#qO^Yjk)>_}QcK7d5P{vvYc48mn z`w&xtPmD`sJ-B;{J5A4iudcNadOWn#WO*Fk9QD4x@HGV(iwug)2E%7HM@-T%# zPwpNlI-~Yxxenu{l=J$T$z@8Ah&s3B3zMub$p~Fc9;lWfnD|l$b9VRUa8X`(BQ$RX z;*-q=TG~MM)yaDlqUNr3?Zg6h6imTPm6&FSwajjG^U{0l!=X|5&Ly^KI<;tM@(d8l zxJ0jh;J9UZ6#CUCkDqpevUgZx3iEWJnLV7QuLjpu#Z$jzs_oBhJXrRnj zh6Et$Q%s>-LKvHx9tUJgC1fD@PwHXuLE$~5V+^s+s$C9?Tae>1XkF8@Jj=bT&K{}P zB&V*{a|JQ6oNTQRY9F#W!Ohx&evxP{Cib*%{L*0k zQjXwbWy#TmKg0*EW6-ns&pu~|ex6mEKDIi2<8yA$`wyqDqy%TIec%~=f;_T#srrg} zk?dR7#KzluU&OaqD=bFbZc?cJrNp|YjVz}4qSJrqPh6hR(-3d0OfD7(Op}-goU2$4vmXqO+ut>$5{WJ??w1UfI||gsBKWpY(P`X@2KLgjy}^CHYn(_ z1+8shO)A!qBH`jyBSA#G1`|xh^_faH5wcFUjzPSuoUx3%g=k^T208w)TeAk?_I>0* z(O8y?lzq@KlkteK8)V}x9?E~lT!}&n|7bdxqRfF$duPQ+A-O^io|UM52;j0{82OV1 zL%Q!kW;zxO+p5Q&5fq=Q(1p;t(1o`opjTJivd&ot`Zic+@>UE#KM*r8(VlJpixj*u zs~ZE@hYmy#zbAU@V{3>op*<5DQEAA4`p1)54jWvsj-%+l#GFbsm)_ zhXnJ)SmXD@nlj%rOm+<_UTTw%^3k5p0VDz zsvk!^zo~bOq0POl-mRl#mP_1`5oXz~*USdq)5|7IF43#t$h0>L^x6zM9FCZuWQFQG z;C0Cyv`$iM6?!~*E7pyGus|b!E~p*f>V>z|)5})>sb0YUsh(bD!;DD1MK?)=eQEmG zP)jvX@D(4_&qO_eUlim(uf{GQA==S}?YZCrlLC-&nP*6)O?YxL9#ug{CWw(B+9Z#9 zo78}uA7CFXCj3`$q5L1))fL$kwDPT{t`Me2YIapA7O(*oDyon8!&FV|!s7IRd<{zR zH`N6_HM%#=(1z6PM7!p^dLS-M@%(DunF@V1G?kiRK2bb{51ete9NfavZo2#aRIELJ z@uTS-mBBUX1LP0$51sXA77sivtN3&Lh*zC%q%l!n%OT={(62x7GxbXm1QRYnv(+y* za&J}?nAjUXOw!);&6nX^lE^~@R2>gMWQGPS1t<2ebkzxPQtqT3dNAFDz&VZ+LMFNc zUPqw=W2Nd;e|{X55t_d{G|*olQkW^g^+xUurMNvS7%m|~gY*9=4{MX=ZkaKN-7 zZj@1OCkW>u@-VuP7SRxekK3ybLp%eYn}vqUEI}-7dmaM4Dw4k&jyMgZxdgVJLz_6yvE4 zH+{Pvi&BC6V>;%){@5}($vdi|H4@l?M?HY-tt}~kP`hhYS;&jM_*OK$(nAFw;9Hy5 z2a^D3-98sYHLZ8_ZSeiI_Qw*{nZlFVZfH~)tW@ftTMw^yDMNyZUCB7Eq{(D|?+TMg|^GrO!8`8?x{ z9O~%msLw+obUigADDQi;6=wQ9(>S2KpH&z=tbIq>Gx&Pnx%oR{CJ&ALEo>#yy)$*9 z_{<({U9AuP{aD1rGm+DxBUNH0N8Ih)bhG(GDo4aye#PHQS+$ol9tE3q>ImD0Os+nU zaE;_YL@Q;JyB=c~)TpRVbi<|4?G`;MBswh4EP<7It`W~}v)!7G`thDszwnJ$UHADL zCmymoJkFdlAOB4GT%1_(_$Q@nTH_7H>86%H-$fl;P&ktDf)arwq3L&TgFYY+&hw^zq1hq4xo-KJ)lappvHqUyodE4iQm>ZrrS>dE@}NM5xNfldYdMt z)3S(e*$|=Y*HMMejJ9k@jtwh_)nz^zm=YD&sQm$3y$$~{0lAS2Ln8HePcB_7lweAD zk(MJTf8v1}E-OIEg0ZgmkTh6I<@&Nt23c$&n~((=K~ygQJtnFT!_QL(=Y3o~4>*l% z8C2V6w#eT53PlQDPuu(`HL&gAjs72BJA6Uu&ZVC&d=shzo=>Er=rZ!~RXVZr)v;-D3O@mzlLG|j&o2Y4^#KS zU-SiL7lxU$RBunr<5DlFOJVkZnh;6*!Qg#L`;HC86@f-7Bt#_?b%FYjGGW+@MQokE z6N(rH*^5mu$(K`IsX{0=?J{Dzx zZX$(Ec9X)KjlOrfuNqLu4&P<`$d66o*wC$iS-Rhsj!yZ{ih(1W+H}C_q?q2 zhH1i}SS=8A)LsSOS_6c)zJntZHc*2IX0kvIGns>e0P*rr8F$=r;dN8raEL!yurqIk`AxCcUx5O@;;3~ryIMyO)!1!=8iufSA`a!Q-Rup4T zY!q#R;}=#%DSzXRV_6dP)Rp4pAjt-~)l0FU+N$#k0)qx^7yP{f?5d8&toZvQU-b2; zEUN~1BXDjb#(x=#trz*`x$T;MTmM0yV}8Ao?UmsiL9o~9CaUdL>IRp_+w`T1-FM;x zCX7zm@an!JmW;?HmPYmASoTk9EGTzLn}x7Ih% zuA$aL!y{Mj{?_Ds7##4HJ~a3{G0e}q@Qr;pJ2MNtMQ^@ai9gorV5=`My$$rQr6#<79MR#M&|7);o zN(u=2tA7mYJ~FMLHue3YYRa%%0gz>gjF6c`?aoh8;e@wmFoHQ>yWnICkI&8RKnun} z?je=pv0&J}K8>873w}n-kQiT^zmrLuWJ6xXF9)w<{Q&=IzRQqAYho9OEe{SF%hCaQ zE+#tg;iVE?JrinXtlPz(kKM+t5%@@9IM$hVeIKr#*FJ`w?%kY92>3}>kR4rOu=Mdv z`K~-IWp*UEA{6TUwg9+&HK*Y3%QsVv`88dYd8=DEBhq?m+f?b(KfKAZ8A3ne552z^ z$cDZcb6+=Y@w)G2=hv7wiRbm|-^Mr}bEXA7FM0UPp||S#>JDnRV(wGodoteZYKhOA zj>qC;yJo95gi`1NrFG$sDsMrT?VT6=UZS_dgR8pFKlrF{LmSgx^-VSpeo$>WywY1W zlpBR*IvB5mm$)$P2ks;*_}T1;x-)V>WONWndDJ_^zI>Tfk%4#u1}sdkmX??}C;fv| z;S+h(Bt-9gfRZy1$_W>8P7$u+PRhr_yIe$9I{6rosgZISbY6aj=$$G^>tZUysRG-= zf61S*OPF-}2I{u!@~I)2<~!nb&t+Ki4chS@b2~%AF^Du6mR^c8g^~}4G!kX0 zI0^ign*jt~tryLsHRn(6aGoX&e~cs=W68A14fY`zw#uN63u2H>ym+g{lp7QY zkBV#=B4VEDW7!}h6BLW`cYaL@tCZR0Z1`cK0ewHI$cW<+>lxb{SsWzkDP{4xfCV3S zWT=2X<3%2Aye&mFF)utvF&P9z@m4_3$;3RT+X+Wy^${)!fc0Ab^|BNfdG^VxOg*$6 zyML>j1|xcjaHYuE?Hk5U<~dVV)z$U`+3z_zz1_@Z>SZ5G@ap%MEU$&nh&c+}SU#bq zpwi-W?c2}THTI~m?97{nOT5~gtLALcdcClM@BT>rOhNa<`J4{o(6uSU?Hwyi1^EZg zW=i`oEI(tbvVc+CN3w;=A%g$&ew9E4(vZg%_V`hWI+?ZI_PY`~tWt;z0c>T@+n z*aW*f|A-!+*pn>4w(S9_ETM?HX&F4^QT;iaLaLd*j+cd~n?>24Mh$sZ-Aq@FmaU5W z@bZSycU^9IiitNb9?FyD#rI9ECs6XbW_CED7{u`D|8UIMM1`ODezOv^6q5m>Fa{N8 zvf}JNr4#^fo-gRbP4aRzP+ht5UV__z^a~HCryB8Ei1E?jWK?KGbMrcY#%5`gm0|zM zR`S|Eo)bv|^bQ+u9Y@X(J;<|Jw}7EQ11zJRAnezFXnmfP%ymhev)4=txLTnX20lZ- zb?lVt33i2Jo`$K_I6X@~yd;g2uR@cRsi0iin88Y@yqYd@ayACYkDF44!r1Jr+no8k zpO~0TxrOEqK~Ttfe9Y-7vk?>SzE!;plpz8K?UZSVz~W0!@<#0#XLx=xL-!g)bz*_Y zNerxnu?Z_A%Zs7P*8SGSux+8w7%f(+Aq52WkTc=>Oyq-&DY>I#u0* z5LsXCy$Q%TEhtVG)M=W?*Fr3d=>q$8+bMhGz~|_ERZ1gaM@tP)>$mBjD!L1lXiRy| zbdZm~B?BAM0fG193QUgvNaWZzKIF@l%Jz$_WQYVM$3^D<%w>M)IQv7)z`}|sVq_c= zt5gn+pciS{4_s?s5|1!Ubh5YLifbra+= zBej>uO)-7<@D36?sGCu!a_A|Kj8tygK1?7Tk&u5VJGlk3!aRYZzhTW}xTRlYfb0Vv z=U-A3l2Iu9C^%|%l>$io{aOH{lw0{}fH1={6~#+~QW5gd>MIQk1HYNI_Co-EEG%Ds z7u&gI3$q1JksdPE0G@DLl7(pTC`J+y%eZi8x5G6S1y}1b2JHGrfe!sof&LJ<>klC< zmg*v;<=G6!wL%)UFs}@DCwi*uSM*7MHP%+V;d!T-_(PKM#Uu&lKRwbsGaQFQ2`{OQ zpqhF=7Ah$82XPoBGyE_mwR2;li9wqPjZDuZUcwWs?Ie8j!w6V>>maj?_> z+rD{5^ZRz0!_F_&xt4qmk-wWl`|D(m6p^AdG=&u~$BsX5j>i;V%S9CIsHP|G70PCz zP~5JjfFt_xN|vt%XS zLc6{c7WM;rl1MNHz4NIWQdIN<-rOD#fa7@|yQ_|xvGb+TvKGat*VeJPmKhg5($+W9 zw~QS!i6c%njJD+zP~H>6%6uOD`(Bp+>&d=0c3A|@Xe2dD>@ISyy78iI((haWP%2Z4 zPZ#PcaL0VlXVmjGlk~9=KJGrG@TN0wvLuPM5TQ{d@%6n(5v5{{Ik}E4XT)U ztPwLokI6iDDIFn@zwxSnd+3$#i|I3VV)4?|f0K{dwcPAK$HsJK@f5#;x^(`b!UU+K zk9RhUrvL272m4>kLcR;i7e|a!)z|6{hRYchuBjC-w+RnKq7lL$^B+%~_FyOFQOYUT zVe7Rt4{Hiv9Gh;{pb+mG>x_fthoG=VCqy!I3tCpkKL-;xYMnX5-7~>C5xn(WO52vB z0KRV~AW)LndT6)alovm3P!JB}#)jDuwrIqij?B&!(x-4`$IKz*U*3Ofw<4pip<;_@ zBYA@i4H0tkG8I(#oZ^=3fN;c;WRKT3k~l0707R&UtvkFe#O@cdaJlO7LQw%Q`4yIG z#5sqa>O!5`xGh-=gd-V8O+xXKuC$_W0Ldt$7sRgFtSTaWNd7Vubq^`7!#Ju7sF$sO zGW$fx>fqHun5Pv4s`ZudJfbDC&j`fz*)+8WRkoMRbKC<&!_5+UN zWgoe|P5DUugwAaYxsGb2QF%yUkJ)I~F}|xbt$|w})pEbhgD`vzulHp}DYYA%+dEPE zsMVB|e5-crIwE%?*DE!nk;=a7rE%4)BT z#nEwhk}>=@&sc_xLJ!6kltmltViLH3Km~lOMdd*aew&N)A4*mBAD8C-amE`lCg>zn z^^h`bHaExaACx9B#ow&-f4FK=rfn5fDs@mb>n}KL3+7Eg#Qe8z7DN0_xh1C}Ck;HqEd@Hz$N93sBc|3>EI7G9z zwuK&qEWAYEy{RugFD7SdM~dlt6*9w{RWDkMtZ z=x*n3>tAVlbsrj8>qtT65!oJC?(yDO%FNgIPlK<>4Jyuwt9@O4k z+|1v(`ZSvbBqe$7OCRQ9q4(c%6M02(q3{2zH2?OE_@vp~iS@LFrC4K6cf!-C>v$$a z&OmMb6K86L-f0dz*hdG(IX2@S@iyE9d)#PyE+a0 zUH{8xGP#K+;~qjtKj^&#{!CWG=?^&gej{fy8mjt=A3erD11!`NI77Hb&yS(%G``@s zj&X#H@cY}+H&fw`Y6GpDL-=X_v+q>^(Nf%(>R`5K3QeIPWpQED@kIFUi4KrIav>1* zDnNYe!TyKy30z<7^4|*zCxegj6x9gU?Vog|&_stwT-!{7Aos4=F#3EWLD?-=gVHm{ zOn08|uO;NB5E2h$goK07jBmygcQ}1kR#mU5LSS z^UK*nVK*V2tBLZW0F>-_A{$%4QQ(#$&L4hu^NP{ODDCizS8aH`>Nf8WRmN{| z5q%zBDdV5Kh@r~gIHALTHEH7$`@17gBMSWIT${8iKxwhGF|;tK6OdQG7ofK)jGH}* z11ds%(tN0EEJMYCTH|T-g9Uvvo(uj#PbZ>otPu8XL#Kf0FvNzBP4w1Bhn1%RH_^4H@2qtmkphtEwsr5AF7g8P;#&xOjsIo8@$1TSnWcYt=av>)D87r05J(-Fm$q@B?4Qx}l2y2P`F8H>MOT|2@F77%0>P zGV)>;LX#9S?DL(^=-tQFpt(r<4DV!e?HQ;YS}zjjesvRg=L;XCOuXmSGyw`VC3A@Z z-~(wa_^T{R6&BGyI#`pGE+ZhztZBXQAH&5IZ2#ZRSilTaOe4RMQXEYoEVTrKSR z;OK{M5pv(p?}*i+(W=Ee#Ma=C@doPLv)gWAyp3fIQaI>#Z?+bukYks?;r9n*#hM}I z@Ef3oF@g+B}RbnETs-DjqopN9^<+#WZgyjuiWAdgbyVK0qjsJ=FACBI|KRt@;s z$w4VmnpuaFko9ZspnXlfue}a^XA?TPmAURXJ!^WJ$nqDdHf{gyzfXiT@vDzyr}Vkt z1MROyt~9glH?R5vD$o{T|0t_48Fe}2ZXt<0r|LyA9NBbZqQor_W`0=&VA4IJ6NehN zg=FgEvsRXt>W<}0Cy5E0NJ|&~BNW+oItAGQ}7y?ZA?lHUJ8c61bMcDA(*uLnm@ITqRcZkalrdiD6|%3k|d^_ zCf^csRxOrj&zs%Ha|cA_UGs4Dq#wC;XYnxS%Z-{Fh_w?s3D+!F$o?%{T~~^$IqrI? zMdsGj*#)q^GKD4%>|or`38|MZeN4~2Iu5JVv70w0_r$h%uEel>xO%bgY95WsHZ}b| zH~8jq&)MH&`9+$E+nk{W?;+dsk7#kQ%z9#8XTTtGWASG3Ec8iD$8X>4tey~Q=bA;5 z{P$O>?j?Qnvfr9Er2&nTr}lge)&+^}$e{U|E5*DkiCOve+dqYThs0M4N)M%aY~uI7 z?~}cIOR2-=)~y>uJ?-h|XHV4b&b1d0206RAa|+O(v+TO-Yrx1%WR=H&mQ65`C$vFM z8HUW+sDkd&q*jr=*QRQT?}i3`j{0_|@g0MAO*!4bo@i5BDJID|Wy`j8ofIDUgGnlQ z#)v>|ifie(mP#9V?j;3vHDvuupmt)u%>d%<`Fn$NfRZhPOa~s5RFgPl<)?Y;-$lmx ziuZk3_vpZHnbka9Q2X@(ehyn#`XzLzpwm(NqU1b=#e<05KM_M8EEsr14S@JiK<0V^ zoxrz713j(6lfpvWGwn}MN_>$fnWngpw!un5OzncT19vJw~tG5N##MNZA z5%j65QY3t1dclNr{~P#3e!^e-J1@5#%^5zX#NO5rtd{oBYrEp`RZ%mJ>*yXpb8 zH>expO7d(KZ^UQ!#q})aD|P07MmhMG65JAqD>mc9*LE9wxXWk*48OGQfj+Q+@CcWW zd33I1_Iod*aZcr7okGa>ogXFoDI+D`V-uPTCsE(3#|}(-bQsv_Z(Ti6SYKR&UFHtB zmAdRBEx`YvyZO}Vq+dpCX)sS1K%9JNgYzbS@*OdgyP$uM;|ZV5u?2&d{1m;8_ov4T zcb|Sb*hILNC8&eoGpBGU$Ul!XJ_g~C^2j92Av08dVw)HK@ouG2FU_tsf8!#~39<2W zaKU}yn#RpHiP9HF!F1_$(RQ#CZy5Ouz6TO{c8fKhWh_k2XE?HB${6ndCZH&tJzAG( z>H@CI=W;w@DWhwVJ-Y2Q=xOs?U7}uO>C;(Q%?1PU+^vap;JZw>E~%|chMbdq3b7X_ zve(A8*Sty$M;89?H3E2(;O;)N68kHdVc>2f4XwCjbY?X8U_VLhlPJ80MzvxT|HXg^ zbAzV(l@?oZBEU7uiGbgKTp1PjHZxq+FODDq_(}l*$KYWn;#E5t}w8)YS&EYdjZuk+biBU zdKUJx2G-3@R9~5^Rm6g&s+RJp1qI*v{jOX~#zhz>(eDqY_X^1BErV zB}eXCNmdUYO;`Fqs2uaJ{_1)QV0iUc%0z3;hzFU4is;wrXV+M#XU-qVZf9F8oLF{p z4!xW)alnS3`k^hecw*&OKf`Q^>olb}D@Q8t>N^kip_vcH+9q{jEB?`m;tu(I2QS=q zfRn157kmC7lI@Yb*WXuPq~3Bqc7_k>BMd;hpFX{QYL<*EbWVZ)F&;)__I0jh(nV`Tm7fi0s9~Kgg-5yyV{yOYXuUYmq=R${+?N3?yrEBD;$fjtG#^F-U&{&S}vS|~J@R&o8 z6K9fZkdsG{h!)}xNJ(NG-`jc1%Y9@w-#ebMH@C2mszB)U(!kmHFdH1G&iaqunP@a?lU|88D^^R(ze4HQBHRoT zr14x?4GB>4$1f`%dDWc&iWPjwXHTCBK0zf&F!xT|Lgmg+^h(8=+%^m=xMF~$*(eYVkMMKihPRW{=%9K!idTjqa5BOBffz zP}7dC1}pSixxqw}5b-xLY-<|6cJhC|9@P?(!7jhr+${#v7jk&f8384`LRv3mEI+NQ zR6LjI11^lpQMoV%E*1>;WH_}(@`YMpk#!gq`g(S_n@X!j`Y+yzSokPJ1#>MJGw&XE zR%K42NU|Wqsw`+hSD-$i@Vgi(W&WH2;|>vUse|vLTz^*(4=?@QM>YwHOT*X$R?NT6 zJQ1wej|Er2|Hsr@#YNSCUEicgNrTcIgMgxRH_VX3(4{CffFRx7NHcW900YvEfTSqh z-AH#yDZbnH`=0lH4mg-(yQ9g^_ip;IBfkSfSFcRWqh-c$;sp3G6N5Ddb(;NypkI?KjpkkOF+8MVC&x^0d;-#K?@$!u(*c+;-Ri2-)0G%YwW| zFQaY@huhHy&9m5qY>%ak$z(%~jMNA4R;XxwY@E%F6Vi;DTF~B?-x3^>QHct__P!pX z?s$3`+{l}}ExTexG4yrAj>IF!(JqW4X+af}F){SwtOx0wCna2W3{hX-DHY2{PpE7t-o&+vV7$*ul_-%o+s zQNLk-4UIdh#{YDP84*E~eSKLUrAg$2wl?bTQ20%4D~#Zb&GyER%ARWrjGTtHg`L0v zyGVEeH$`W%JMtmJ9VscVw_ljZ?K%<#rB)?D+`+U_qkw8}meF{T$cb3)au=EJ;HXSa z4zCviTgY>jai2l1kAt|`Mgxjg#Gzd8R3t1|LrtJ{Wsm_QD1InVpYo;<@>~!{0bclJ zn&Hq+XjCK9Y9>McOvERjYM|+q^ICk$^7>rEZqXBlk(z;D6KTkiDNi>(7HJz{UJcnr zhdv>!#UhFC$EfKDg!d>OPlXqp^QI{*n@agCJtfb3IZZ>5byeTzh^m{GyW-T>P)#Xl z#F}+*(nz)m!m#W64f>V48BMI8fYtXJ_r%AZ#gSE-sW$Mc~sJ_6zJ& zoR-PhDU~y;UXGKYg7)!7L&?(n=}^rhhH8esHv^i$R_I4y7d0}NivGT93v;DGNkF%( z9h}ecTa;E|Sf$&`K)Qa=tW!)*Ir#3Es}CPoW!lMO#&4yHE?z)u2xVUpUh556u|z;oz%Z(nln}{=Pe?*9w1hb%-*j+!D1!-66Hm z?VP%H4_N`y#aH?6$RfS{!+F)|TTebPHVC^Nilp~K`*P(R*CgBQg$D*{e%2aV@vLLaKfWL{UeNK1PcY_U<&$xjT zP+~107@I=XLp5>Eyb{n0!qQEU3|%DaGc>X5*iT7Wm(;^H3U!at;kC2o$c)yAcy|8f zQO8t7W;QYXxnJjUyhYMN<-@OE0keN`@iBzBC`TM#jYa}`h;mGk?Ea}{MA9VkCx+=0 zyZx=f@5O*PPV@Bo9Z8Ds(*ZC3VN1_wjjxnchlBSUcHHJ4<_3_NRpc*|8p7nO&nQpss7^E`LzPN_x2n|)o?%K*HYPD)tef^(`6`Rlo)_4#LEI7 z-LNP(tZn$!X;`^@^m1!ppoB_02{IEt64?FWGQcXj9=WgVjXCcMUR2=pz0RX$3A=K87~{5c8B4Qf%dvh&G5K!%&JzYhT;QmA7(grw__y*m;dG z?cDJm;X^c?sQ73YbMX?ixJfXh4mNd9mfyZW94>o1p2+AwK?Zv#FAwTNUjgyZt8F|L znN;%g(w)vi^Mt94g@*9xUxHtjSKd^=dL1>D|K~!}Tl<#HShm0pcRKn|^u8BCo%_Ox zPHbMsVj->D``cY!yWHm@T|-E1%O_LFI+rEY{Y#c_9x{nuM(yZTNsBsRh#D8KJY^LX z;o_ZmDkkBmF41P`!^cM~Pv%uV#1^rvOe)#K2mo93Ra3CU^s*sQ!$enHH_H#P_uAau z3A(z4C-oilHxw5&XvLJNl(N*xBi$RMq-D}Im)wbR(@RFu&|%x*aK7(5Hy{F(?pO|9 zCyzJ*f0h2cp#dQut_K)C7b<2`8&bO@jm<3%r7`m-@%IhF zfKn|cuYx=VNtL(Zc3(`)10{Qb{ zLs2RamUuo$3Tl`FBpL4F@cqQ`Qs7sG(!@Nof1JI+|Mg@|0*QK2UOhO!35aIHcDXmT zD#d9T3V2vQkb<^mPTLDhldDnygItXv;C{U3LENngn4q4n%4q@DO=94p0_I!$q7Opc zv8RB?MT?#zKmuTsuOHhLl3OVtBU?bU<_lnCUH{rrj`V({B4JZgR4nH>st?VFfP=i} z?A67=$X~3@RBlHK3In>zE!s;@Mg__1p@YMD>3Y z1D1UVqbUAep60f+-;*DQI-MVt^UVI;FwP`Lj z6AD7;1SAt?S>u)Fl6k|rlXD-#Xv$>q?u$7o`y159?A4i5>Xj?xCmLd7lR~a~KNgVF z8-HzXYpZS+#&MOXbG{f(H}hCAzG!QyaYClt(qps))t&li<+j}JtW#uCp@kV5n6O|_ zidSy0V+YLqrs%D9oLLX9BTWjRnXnICpxDzXYr`i=ArEq$e;+)k4|I<;1fw}?iWcC@ z^ve1P&_0sIE=MDgupv+wiel2~)sE6$pT{@bfd{UQ32OysH?L^9zwN{MW|n)`&^X-` zT1L*$!SyFLjIV8VS8Dg z>5&g5vu2Bj7$pn6V`k3sgb2&Bp`fotNdpl_CgQOy&KH9MsinDEh5_cir^g(iAJwNV|Flgt1(6{_gn4 z9*H}kQqD7PR$eekKGHV!$RRpwfur2{ZEwsMJ&hWGZ7N%mrHHYI*xpQDf^L8Eb)X4tMWoAd3g;m&x+Ko$hab*+i#{JPw*5 z%O#;ol;=5}d)~0Io8eVx5*Bqc)(q}7Hy4!X9L%fhPrPfh?Ls*gDcdn zDhES_8C5tT>YWL!#Z73j+Riz3Yaz1al408o00Uy1GG}yXSV&_flZH=#&vu3N@Wyt9 zh1G_M>8Y%b$LN&N^b*kuQ%A*i6)7yaE}!1fBlXMjlez}Ahh3)r$#(t0zzWw?MDt=Iw!B#n`h@##GO7Wv-y{wEl6!4%HZeM zF|VF?zF$_)Wid?AM)FU0RO(B;aMiJiYdvnzj{NGUe>#i5yjQj@V+U_kXIP%lrI;Lv6pa0B2TBdYOkq@9<0w+rkO~1~is>cH~oMC+h3So*r zo8Pa#qnzwvEBWBE(&`W}ZJA59*~RK)(gRQB|CkJSa^J*;gXxIU?!@f=X+f`iWRVX_ zu8{WheJIqUvKf|)G@Lp8GheaJ-3le$kON^W<2|tIfwj0!03#vZ;&t`Dc-WICf3KzjJiL8&HQLomZ`Pr58$d%6Fv>q*qJXgw=XWyU?9?Ym9Fl@`=Q&_!y~4Q zcIS~3=ka!*XD1mJi(@DFB8GmMh&Lbq1s-p>5c$hg1!hmvuAf*8PdBJPB8!AgoPr3d z1SS6Bs&w*p+$|_xG>`}&}q4I=}0{98{XPp=`F%gp0=4kqf#rgcn3{aFEfa`S1aFeS@9XtHN1|u18^E0L&8(d=E0}w2ly!mu`qkLH97?%LzGTo+1@l80#R3Mi*HxuPj(vv6QlY5hK=2jL~Z(7%10d1NA-K zw_sG~Go?nmD)4x6+bucBx@3c?BxR%X21GLxeYH99z%#lP2|E0RQ|3Wym^0C1hs8Mk zW{nXyh-;wVzNU#K^L*-n6x#VB?{z_cR1sZ^qJEONVT?>^EsZjUfPsPwNx3-OJdDnp@_S5LOq;`#HX8%htkxMY=@$%{(qndqQtX!a_ZNe>Y%CV^$3 zflldZXyy0-Z`L~R(FQ(+2A}`$8WBx#`XrZ9*%soZ5njrv{y4Ya!1j)rYy126#y7be zv=2_aq!WIN&zJK*)z6CONDn+tZg=63mv6D7y)S-ZPSt8t>r{_-y@8vkR) zh|y66&|}-dsN|@V7DcWpWC-|7n_!osg$6Q`&52ByBA-@KlVXS9l_uLQ^@yTcLS-Et z`dn2+Sf}?0fk~)huFW{qEZ828YY4n{d}&F-X9KM;}{?NpihDP^kwfk{F(Lw+uSNef11T0f_ zQpqjrT2Vb-)gDz=KXStSFG5CR^54hZZks6LuJ8TPKMc&Osr@rEykbCAoUO>bv1^z* zS$WYqb>eR}flP#R(QQD=kPnYxAl$P+ZUhW6PTes%fVfjOM#aq`m|uh{gTFvk7CiwY zJwS{5b_I^%L9`|&gH702b&8;yo8F&_ns>6~QJsbKNt{UPkwVT;1a8?htEWDh<{w|bMXK30(-I7Rh1x4vZF{<)N=oU-m zJGvKNyDPZ!KYhbM6{*tR!HT!{hnm1kw+atSwVlGQ8P5Bf&whnvHvsRB%+GYK;__+G zRiJI3=1clq{*_LNuGNv4W4!X~;`3bNxf-8I_Z%@r$9-^=-X zL)gc2yoeFu;-J%O%%b|cC4PpC8~|NG=C7VuSn4f=71 zTjW)0I4O`1ehs3z1X6A^7%1h!C@!f@O#@k1RC^TYBk)d3ZT;_^)-3V_bVdDUU#ApC zy)pO()kth+L$*3coU4f{GTf(=Lq6n{PUSiS(t%Q0;(7hvc_a);Utu;1{K zQ=XZj%Q9}#GUAeymeBm`o?C^G^7DBa>Td5wnjF|v*jiwZH0l6kBqDc0~ z?JG*8T{cV_8a*hDWKM*u*B8wI_$~rjVw=^&L9tVhfv(btEpiRqq6I0Rgtyw=pHEZP z>1EGG#z181-{u5Q`+vrnOOFaD<)5$yO74O5JX?A36pR%*x+2>=M2%>EQYqv=uA$IX zwwEiiE#g<}9w%SSz(S10)Gb{3b&Bk>>4Q7%#ZP`^AoOcPRa!1vI)I77$lwcB@ak$pt` z7~u%|gf7TXxlJ;lghoHHfX7FfOi*~*latsHq8Zq40TXg*jpyoG=$}*JrJB%R&4H^4 zefit{=m(}W+`ICZaavsE-SsKhzLfP|9jmQbQo41<(<}h%PY4lrs0Kq5`U@sKmLE^| z^Oz;8m*<8*cpe5t{H%B3B( z7JC30;D3#+nKrN3lPeSqSGA!Dg3R6#F#%C+V7|Co1l}^X5pi8pMlXBa2kbYzuj!0< zbnwowL074O+(}exdjmXtcGXCXv~H|bkt1*@ZLSkiGZlbD?8qV~uzgV6I;y8kX;C^m zdNun?+9(<*DD+=iVL};1wYrI|%G+T@gM6$K$tlp|3awf9vCOIUcFs=}O+JG<@(E^D z@l;h-X*%+~zn&5Nl3n5V)ia1Hde{}|8K%S*1uNDA?TN%SvC1O25$7h*vPs1s6po*t z%a{z@8Gx?S`@zmJMK|Xu6|dt~Vkrwelyd9_@TnXfmKPq$K2`0+o|rhedIamQSf=oN zkOWhvcUc%Y^AJ6aAhzF{R8wp8z?0E_-eHL)13?Q6k5CQuT}u}F+2EVO|HF){y760J z!?Xaqf~~CODHz0aGS)-(4ZB18;_6Y8ovE$wG6@GsjMvf_Z_F;Btz#5ce~V&}c6KPw zcW?I;l@go%%_X77%ts=DnU7DeU*EQ--p$e#<`x3$%HI&DgG2aC+j^BO{p}{IrkWG)?FOsWsIs`J(3n!P)!XZIXPHIw&8r zNPHU?)EIHNw7WZ-{*Kr3yUC9Im04Yc&$S30Bmm)u=B1O{5%3f2AAI=3Qra|g_ZR)f zC|*;ZHmD@54gO;JPDvNRV=|kC_ZRL1T7&{X&Wua}hA8!~U&rSS=fK1P6@mU(n^t ze`W!kjCW&5L)27)*k~N>#$fS{-{b@@BJ5@*q7h~k!KVw!h5{q)J>KYFVU=~yMnlj? zlVdt2aaY3rAzd^>7|p1 zIVz=_3}Go?0B1Zymr`tuO8$@>wISc?8|OXJRB@Q!BLhy3`lHo4h8kp3hSQlInoVRL zo?1uS#6+c8H_;`e2RzfyC~(U0^#T!!ZN7-=J6e)*dVYY!#E<2(Dek&$*8f8OtD$Q^ zuu?XW+{oudx+-Xq;L)=6!)KnV&yVK}FpXKZc9i4C@C}Vk1$B0~xfzuzcm((i4Ji|F zWs)9tN!Wu#+2!?ph96;YFU<6#OSiGLk0ZBk(G005bNC*KH?+}qlC$Ex6?x;aS9fYc zjHcsUw_P=w+C7}2r;96HQBmVOEk2beDBvzI>r*#0ylG>K^t35~Ty7AS3 zP4>$&MyXzFkEcE>ejEtTsG@!Ifjk_`{xifI_Y0^E_r#BLR#qHYwj3(@s7DPxeOn_U z*x>J&_sZ8ss^!U};YhQIE?oo{0U;Bw7UlK$H(H1@P>~HP*hVssDW-z z-puE>e)?xe2>Nf!Cwkeh<^3SqI`x%KqF*ST_bOBN3*ei%k^=QzTee)#+H>jmTnk#< zBoeRYE|ekpnL2PyxB#u59+g~~0)nFWxO(+Khyjk9O3r^ymIDzzxT?>n0C+Fw;>)#4 zvMeh$3~Y6s^X(>Q@Ob@;@`X0Hh-d}Nnmb;u)epuR4z!}8&?g;uo?{; z9TZIw{@UF;#jk+SVWcq&7h?L3{L$oMS^|ef|1i%c7o#`UCd)P36ckM;#F{Go<<#(@ z3NT}$YfBS-|HRCM<3VmL7lK~!zBAg55vf4SxGQuj8CEp6T0OGs@RZE^>>N2|uzCMw zP+6@9z0(%+Ry+1E5}#1Z$SA1dy;YW5E-O(f(eZ3B^#!8Y*n#cg+1jYHtegjCucr0O zn(_L%wyEsfP(XO^jzAOA;+h0U+*ectN{9N9TW(}5ZXR@(OPT50brfX|;(HLTaG2e; zwcKx4gfI5kQ+6BS=h@n0ewo)>>ol@bf~*WI{qDXT8cN#R<2aSLva@V#$wlaxaw@wK z>)4@ZF`e0A`2v;=0{(zrip;M)J0Btxj!$ijM(b+CyNh_uuH|I5Y#zRkhM5OZ4cD@5G-ysx&Kah1Y%fa zS$xrHR43N?=nf0@_CV5a9B#*Et;`KA^xbbLl-^*%HF^B`H@)<4o9a>`m z7FopS3+;asw)npZ>zuPWhWzG;Votle_8;xPSpaDEBI&%-lp7GyQITFN!81<~Qt0e$ z*h%&|dk0{LH(I|9FVO%9(eZ#Ykh7~lbO*(ajVp#gFG1EDOXfr` z$({JAT1J!rNTfs*HDY*VcT;`ssF`?{WaD=Hrv0|4&_|6qKIk{H^ex-D~Fc}|Hb zrq$8SZ#BaGgKYZ7&ZP)1T}`TPrM4tTmx#5apH1p)Z9+m=qOG%HLBb$>cIW=^8@By& z%JzQvYXUROX?3 zFMOVz;85|dak-UtFUU-5V8@qn2<$O~YpBBI%cCvM^IVQPTcyY*C(TTblop0)bNE}t z@r&P7ZNvs@jc+o`sic;*WCye!#mM^KO;3Ja^&7fd-+?Ur?9EM{aK!)@XJ#`kR&Gpt zu>IAM^^cY5gNrq}$?QS9i`^8bpvcEM=FmM%p}A+r0#e~Z-hZytg&K<;7=fbOKUmN` z!7@+n^oRFe#kX+^&ag3}IzQ4&?_L=xBGf0v&?nP8r~>d~AYso8n@!L(86_)otjxMR z@&13wc&SCt?1c+l{9^V3Xw?d@&J41aspIc2CdtI&Lr{m%stZ#`Qvt7q9alWEjkk|U zQk%y@&IeEfU4TE;+OQK^9f)st2Lax8<>xzdp0T41?w&f&D6nLR37maAs$HYfb2Oh6>656`Fv&sj zz`~qrTFy7Rb8VjS^ z{uZc3m1yKjde1CrTvTVef4%+8gjzi81ofzia&rFIvGoqG)@V-e);zVkX=Vz-C-Szz zEuSUXLN8eeIKHgd_9NE7HSXJRd7$*jx1snB@xEyxD~%8^=H{+3%DD*Xom{j0__koC z3D)BKDHa?Q_k-g_dHWx&8(HeNS`;7t1oKT{d@7jA0ok3L(KJNgK8mv4gQMuSo7w$n~V=yc`@(>z|ao^T9(ubO~7qASZJGp7tyF=Cr#INU8_dT?cQ{M2-_x5?~x zj6`a?l#*9;Kj996mGNgY0*y8`iVYpT-hZkEvV;6asisY(4k5YPkUv?96!J?r+LF5* z2q1qEsOZ{{^@pEJ>M*~Sdb%k=^EMd>P!9Yza4)jn&GowzFaa!E@5);g|q^ztP_)@5f26asFWmk>r_h?FB`7p7&6h6 zOXU<7aR-#=`~)X(x^B@#omec60H5=%P@y*NEy_~^J)oZAODtGz?`DNu8`Yn<9Gr8( zG5PjtmHxCv&MdJMGt_N1X`?QPm<~&-1?2$-@9*n62HB91-G=PV!yK1!1gD|TO4LcpT=y72a*&k@8Ua{+37!GUfeefq{ zoVNU|nwpn8aHpWGGf`@}OfQf~7x{%jy40x!^k&>i<|1LdFts&Wp{ZuRBZ z;!NG_rZO7J$m(}shIZqsibZjii)Vstsq>!_({ki5VCwx<2%J^M4K7@~JwO3WU4LS= zutbHxCAj?9ko+OFR$|=`$ILo9$f}ANiRK=)i`&3SSCs@yPSI$7VlCe#F*m@W#m813 zLe%%btzIXvlLYV!{>9$D1_>32Q z;nGza4L>nI#~b2AC@o^;U*aw{btAZ^CP!>K2q`-sYlISp#UILf!{0e4xfY}0_Dm>x z^liUrYpA7EQr zs7lUmU9d1~28)nDVn9k0;1;V1RC@wJX$kT$Hb;V5zs0%0;yCi6aQCFP4qm%ASl?$9 z9xo-iVxEbSJhTRuU=E5a3w|GuEPjhD(>8dM#^g2~%{HXDJFS9Go0}aPbE1&aUT~2`6X*%|Fjf>z6c?6v&W~khV28=hpv%ukzOeY5tL6nv} ziF}UOAkH=DaSxk4?SpewK)CewwTqy+tyrr&HdV>sQ(pk#Is<@VT8-giv&sXlP~NT* z6E3}fgqT<`8{1B^mqUu~2?@fmbJ|;_kX$e;nyq16JbK9@UlDtAyh6!J!U5 zebi=e-`ft2$mhh2&?|V z?8?Qf)l>6kj{a`|#`LD+?T@6>>LV5hQ(KYebBhso+EgK&Xw=OvMDFVXR0)g~>lNtS z>jJd0#wp<(cj=w2+Zd$P#Ar)%`q-VJe_%A^O!D!hX^1KR3I{uL6>`g0fn#B#PR zt|g0$d7A5w*k5kFJI{h99z0iD|3cOQ3(PoPOQl5AV;ab2lnIH~x(mS|cltsb+pnhz z%vZ%&X680Va_Ae6S<1SV_s|YyzG^4FP2k=)Q`l|lV9Mm}5rFFzzL!0-Tpx&W%sa%F z{Emhh$=_9oY=3lW%9yi{n}ZRlPA^CbS}IZD2WW~a?-2V{2Nwc4YV(&2XXW`pFqSTD zo8wW6itu0o-QeZ7O>v05spJm}r7klL2=2+uzpq~u;Te1l?W>-0pnr_8FZ3Fckup)Z zim&s#rdM6}uWOD1pliN8qS_zzN>N_R$|ehr#Vo$*}B_f0rsv4z~IBHLyw{ z?9)jFk0*#Cr_QDE4v2!Ej-EAl;AwkzMv#As5{HxPWl?obbzo@Ue-xuXc8sG&FrqMn z^gITW8PR(p-weEdad1c^3NaSjTml))vLSah)%&bVtCuAO)194#^>#0dV!$8R4VX+` z4(|}pP33$Dl67WjG}ID|f>gM>RXb+pq{$VMY>&J!do%<_yg51i-qEn7(LG${j}*`gd%s>g2uA=&jFAV+q!~#%Sr83|-LV)`QyOuX;96JNg6U zvGJU&@9NO1PF>&9t;*U}C7Sr{PcwNxE~X^Um-71EGgYWWl=&AuF~f`eiRrfp2KI;3 zyY1H}_z~KpHNyB&!+NZ(5ie|9V|qDM=_c+ZOBspGNHw)WJye8Gv1vP*ZGHYRNdEQ@$aM{WC~38R;00=A48CAD#ol|p~_>y1aL zKlro{T@WGlnzIbh(m`X*Ml2^fKl++Y+h-pX1s-ezwVCe7y4!xF_Y+n#Am6|t6`KS# z!y_~76(Vnv%E+EkWx~>S`iS!8tEK-O%|CMerVaH}deCV`Mn4>_3m6ujheQdKnT(ZY zG&!z#nD(GaJjl=L1 zxFE<6oFEGb@;C}0K~4Drc9K)A=Ll%Q)F)D)gY4~(7TaWIEud`70yuwluSoEKMdl+> z0H3Su=TGUY0<<;zm*YH3XDc9Cq#BrX7gK_rX~&dJ7q8us@r>cfUx0hKAFGJc+pZ$l`Tz z`PEamqxIXHD7SU=96UBH+KymsPf=9(9hqF2&1o{DbgD3Hy?cnjk%L#3=<}Y)7|q?m zbDp)rU}_5FDSAoLtq-m$ZE+8ZO_~kk)sOhCrsav2tH_@-I&}T=n%Kw@G;AzK{!9 zNQ7rp_F1erMfe(=u4mgHw|GvvpDf!x*d4cdMhA4IyqvZk+(BuYIC&0R#fVtnOcf}G z=6=}KgiF@_xsq;DUfpnH*uufRf9>9fN7f{(kZP0J@iFXNf#&}9Hagv`p4)8nw=b1F zHw8{K2j^3^VQ;aAKoNY?ECuwi^|yb;+fOLbV!mAi!jRLd z^eVATpmO$;;;YGyvM+=0ks29AO=yn;&}4{L#*6l@|N47eANr282w|YJ54va@lDR9? z#50NqDu3g&H)u836fzejK1ERcd98@Jo3Kqr?y%n>L!#oNYF+fSJj38*&&pz$i73vd z-uQu+wo8d1 zeG-eXKy!&Ny>b?MpHh?MSbv?1>m#_1kx5sHT?eyVpSsZv%id+&TFR#VeC&Q`@R(}Q zQ97+Z-AShSbcg)qRuHsw=Xp`KJI#e&i;elk&zdctO?>o)l3%|O@nux-dB^^I!E(@5$zEN`4vNJqZ+F5rqes!GBPAHr{ zk(JNP9nHm$M{_!5FgNmCRi|Nc&rR1MhdT`_+*AIFq0i6ET%an+m&EGqE%EyV>-7X< z;UYLj>Uih~p~wE~dFK2LkrLr>T<&eu6SR^tFZ}7GD4cRue~J!o4;R*>ua;!BXY^{@ zrVL5*K6h=G$Vr^}iRY9~VtP-#zT+5kWG*bMtgMjq88`c;Rqfx2P94xcty@d^-HZcA zVLX$2z~vJAmPN_Vy*cVGSU(?KdPNu`$y5;{lw+GA-u=1(UZ!>i=?PDeZ)sn>DZw8; zUP5k*aOY~iS+7i!eZBZQz*pkzV^=R*0_(^ZRz(_{dX@KP5-uEs8YrGs)A!7}M6*8@ zr!CoK0s4~V{Mo>ywO~c!_2Ze>nXT#rgI=B>NgXfC0@v(MYr9WB4R&6|u%hZOY&W=6 z;msXCI8f&y14*zYw*BLA)_wPM)@i5Z(eS&_><342wO26Qq5;lHGFgO9ac&ch+LJ4> zDz=WxB)n)pitJr?A9zUF3%LgW+^90^l+|~CLI3;lZ9edZqW&gZkDf4Tui~mMXCm${ zUvy|JA|LLfnqiH-B@!Kok&A-nDXCS4R70S&lH+V^6I#=oiiDcUgRT?;Pk)!Uo&HXO z4b(xkJYrw^sOW+g*PN@SoOD6IYug)a-s~TxSR&ug2*P%Tz(DZ3&={yzuFuGa5`YDs zCPx)scdyHF?-xxuS1Ok&u?mpe4{xy37X1u@K5M$Ig@NR<5~Zi^<5o5=){?Hbg_lp3 z!&zgmBz1pJ{1%p`q<{vuV1&_SOS-;4pdai__Nuq-z|tkWNwAf3^iQxI0=&^pud60RpwI!&eDR58{N z|2g~Cryv{-?=Jgbeql)<(|6`0Ii(Sp_$^$MUj93{Sy#t9XsIl%bZ3^04YNG*j!Qhi zIjs0if;l_bnzX5>usT)+i6v)~v!C2FitfLD`SxZk6rTZ-2H^sU5AHHh!YNFk@_jO5~U4UJK!k7tcJ#xMN@jc=$rK z5qGF5l|H6?r@?VHo%noklOucMZb_@Jd$uc-trX<;r_#4Hx4-n<th&-XPG2YjsP94zL;D$nKdav)(5Ey9% zr){OZ*J@bWB2`mO8qsx7!wv5%Aitl6sQoc};4q{69=XC^=4^j@ge2^cz}7Akbq9rh zCPzZ8eq2hFK%chb6vC3T+;yBj$e<*Hq3w>}UuR;fphUni&?m(!M(%t@1CUnlXI-!- zLY|sHCqq{{{i9O{gLJm5^0c_ncXgJLQUhvzD(;q+IAz*#rn}OW2^(CB&+lkeEiVq9 z<(&&_^YS8OpeWGJf}s0}u@X@WLz*}J4@E?uoWqrZ(diGNZGGXdLmmL*NR-_zC4xMW z^-?Aj^Qg|No%9Ks2KRmVx;@#76coIubi8x(GkJ2}gQa+;LsR*= zK0_(yF6^B8tmHJv=%LKqo%~6EPe~o_N8LIoik_bSC`_ZtSj6XZTu%?aMjQSg5{l!` zFT<>g8{I4ns=e3u0y47$CGc`w>urBF&yfT(?ie*JKt%p@2GlIgO*9YPK zXz}^Hot$ecs$8dMsPj&0yiP~;J+h9y{mTv>%0i#=k}}DyXt|26QQo}3yysDTW=0* z7u|=ch{xZ-%*`MXNp`Dl{M9c?tV%bGr5KK^4zvA@jaL)n%mS5D(6pm)G-5~c7pMFzwHdn;yJusi$a6WGX)0|Ek#Y91Y18Ts`+ zE3+Tf3_YsxXL=57CI8=JzvY#D6^xo{f3q+15ygDu`PLZzgI8xa_3q&Boyj3Ick2kM z3|Zb3|9d-%e*}$1q7^5q`2214B3>HsBk_zLCgxyMA-p|s^mZeF78hxSuJ-MY0f}f9-FP!_v1uReyCwx#bo5NFY>}CML*BE@W`a7C&gI3 zO%4?sjUrTK3;y;(RjsjO=Cd*S>$mEdqqAWhsG^99mnYl_M^iLvTvfQ?36cvBU0vw$ zg9h#BO^r{UYZJvi4)-D`3h|bY)KFM;Mc20aDgBd4=aeyJkou(}HtFwe!hH%T zK-AP~bNeTdBE+=-3@n+jU&=ifkZ{I9$T*6O|55qKG zeDPaz@~GWN6s@3DUI14!sp+0Oca>9_LS1nCsE4g*czLNtxtri&pb&be3(Jj(*)lX5+Yj0! zz#x=i%W=jwZWAdgUm9|l14WfQP3FVQhPnMwPUIv1YxTZy zKS|0LJVdQ2AT{{2oT&7PTmF1-W!f~feNf<`n}Mpyz3w3M%w>h>3--w!A-~C2;i=Jg zuvEj#i%37hj9ucwg6GSOIuLR35g+w?i#v>9)@ltB&55PmXIF0 zVSpJLq@<)96b7WEk(O@3Gyikm^{(e!aWiXi^ZTy7_a~=#yZZg}3;M6M{-u3ZBg?o^ z;JU0GNWBTkO1lZEc1NINIGus4pnv>$WoK`1a>2pjtxy&Ym^M036P|t$7-`Oqx)$Wv zmPM5I>>$rm6@W0*buRb^n<4_bbP$-Kmg0Gx%ftpyLim;?-Ob!5{wugTKAXALXJQx0 z+KD=acU|;z!+t0sJb&v)0s~kekhs@VV6N-Szk*^ZagnTuIKxIP&(3cV>23Loue{Dxx}UL4_dRK+%P+)=;O03z14=8u zo+QvYJiT4(Akme})33BkV01w~p;86Kze!M6eKX6TGfPzc`)RhiAKjzY6Yq$AR1ZdS zn%DJ91-Y*7rcS0q2VW5y>htu(1hRNNK$g$weTw$b+!gxc&vflDGU;Op{CIi!+3oT1 z5u-jOspYHiCG#u`A!PKUi3des`xEfG4vv~*Q|}bpa#kba#E;Y8yNBNQ#wc<|bR~nH zL+^aO?M)Y;FrF|_#2Eqtt$pbc5BYA*(04z|44o@A>3>rID6>1t#Zqx zVoO5al=Fq{RsdNL_%ybeb*v@Jg6e#R+WA5*G;q}G!J29DqF`bn!rvtipbXoi zfh_wPzsB4*Yj(V}J6N^>uTyT-qVP_wE>d`|K=Z7WgcSaHFE``LILlWPP*L2GeGdU+ zt@bALbJwASxPq}2^8}w(HuYX2a{o${X8ZRGBCxn$RPZP52aM#^@S#JkMuPY#HByQ~ zN}fXo@b!e103S%|cYkgvbf1$eep>HTA=6`2Ga!S-pGyFF;m57fXjJ@cDdcb!f9(HE z0rZ*r*n3dF2_YV1vK9Uj@Ynb4{%20s#Xk}~H&%NK_kYA75FToTd>xP@$SZOIoW^!;*-$dKaWgAIC@Pdpa z9CFOXO}4%BTsP|zDVMrYXB$DKM;sJMoxoH-kIGRG`ZF8B42&T+>~Iv$gUjM28fXNm z1Or{Bizl>o)j=MIh`-W^0p*1g?d_61AlhUhsVop>4mqd zL1#W4USpu`HSwRXQ#a8~sVcF&2Lu?vm!|U3p9nv0&SzK8Il#ZRe5mUz>9F;6<#9&d zq`Ty96;6JSNmWM~b^hwY77;4S#jbh-!cXCDx)98vnO1HS5g9E@)7SYI@q~;%-=;H3 zt}U$Y>oX40qwPP)Vg}$cf1KZQT|pVWUgamvfLoU)%(u6Q*$Yj48QMeHXK-iS*P|a< zm8q*32gJXTf?{kUG9nEGE4;rDvOOQ}dv8J=w0<5($lo26K_sen18F51toXiUw)6AS zdqgX8O4MTOX||VN5a*OQ4U(Srd>zL+r2u8s`ngew zsYCiJDnHs+r#sOoFk`$eaw&t^P|>`i?j(%njgPlXUDTQ7yp}1@Nhc2K7e4aZ+mY1E z5%Y0@GmO2Mj-^yoZ0%S3wXbldmXgw>(0h12+Z*P^A7*Oa6NV^GyW$(l4qgsRV2qBt z=eyq+Kv(SSceGVYyQxzzd8yKvMC&_85&$C{FO}}By7#YZw=O$2<_2?gk;(kcga~%K z7S28~&AZ+%qrVPSltKJd0Jo*Wi%)r`-zs{@gpSWBl^&R<_LhbPpnLH;OKhWKWks<# zFgfH!FXLQb3qGPa37B=j8nOS|rMZ<#V+W_`Y3bE7?}IVb$-JLGlok}^}}%wA!?SuA_!r# z+Jk8iRG1sab;>mWf8=_daW`#i z(O;aT2cs7&boMr;MK)})39|s|O+4!lS(Qj#-8%TZu@}gXFIjzjNn8RIJ)t5PYFxNH zs!jonC@WIhN_P2jY(TQI^Q|fb*~k!S&h%*-{??=WfyrQ;n6H3Wsq9`EVduuHjFUIzWX$k zujcS7!^mHsd1>w7$H(gPJ?e=l!7c7g)QR|XQW$66y^lAV)t&t~r0Vay6IuJ+MMRTf zhMXDj&NlGvThF%w&aPRrR=05}N2##}E6;DBm9uV}>sP&-TVt>3ggcdbqxLV$sJll> zQ1tKx*7W-)hZ$~CaO4Uy>#_e-HHEunEDilV`ZgCEmj=Cbvr&f*szk*)MQX=9?g|&>8&NI zcauq?%E#Trz{6{9Wy!PE^s)P8sl7pUWC3rA!?Znqt+gNI5T_woIdt|%vM?4QK(a|I zX*ine1PLMFff7;@`+O!bgVxvi){gFIxIyrlp>?Fd%DU>{UtAC|d-C6kAAh-8sbX_Xh28HRRrZ!INv(_(2|5YjJX<^ zgkUW>f(=wI=ersI`wnd92r+d(;Qa4u*q^e>xLX3Wqoi%3Ptoj|JUGaI#~-pWrnPZT zpcZ7MxPE&~yzUQ%cl7%vo&;rq5yt!ej35!-OGY@P)&uIurH1~CzO-9b*3gmfzu=gw z>pJORJy|$!a3azZ?I*qLjH7`)O=+ltx{78;JR_#i#QAHaL z?UAKJ*XzL-a1+?^+&pT+EH{ZxBDmpn-Z8)RL%BfZaogH}n3lfIpINb^j`0o3JLcZB z21HCay96lBh1S@+p-CfAy(Ua*@tgCsM;!v~Ok97Z=Wdw)gZZrm=uT6IY-jtlUGiMv zw2MZB0qkYPU%^qvDbC31Iy1Jl;`$QVNB>%Qx<)Aw;^#}$_&u2USm`6eyPlzQyBXt4 zFXyXsu?>~Q)mkWWy{k8Gx}HQcSBQEXJ7x^q0nkH>tueA$L`_@7^M<`EfHpzmS*CRd z7A5!yvg2qq%^E4NtvVb0_TYPVuyOz9pkUgUzfTIWOVsh<8TI}_GLZY5)}x~%wt$9; zlv3CUEWq>j%ZBYjzgoZ6>F+YwWv}w%#KFnxBDE@NaWN|I8+tr+4HxRRugmJoOlOAU zzV@)#NO299;g2RaeC-cMb#+C!z#SnKC!O{_snV@-eJ|o?#4ISdTh>&occCtp ze$z%AuWq(iT^gsl?K!^dK86buE!G>}PY+$Up#5^YdFx=Zh~bm8my3P)UDwN>N?q9g zVX^Q-1nuA9(s#->?9q&bCa`|jn&=06<}&TAT)vJd>!s}sr1ueRn7TbV)uNXQ+1k4f z8`?Ip(T}%0Ey`YrO?`e`CGA%NQ{vbU7@wBh&%OJp7&R)j#wd^x`ZPCn82m<9iSbfF zE3T#MSrM&ML}Dg8YwE7% z>h2tRq8^m*?kOD5MJCw=;Jg%3^g&E@m6+|*>vHN*W&oe) zg5j~bJH{LLF!3p>jJx+f#09qK4mdzpMf&JRcJZn1ySsz?SqKoMHF%;}n4SQtfXm1BAB>ObL|nR z=zgF47?ohoQpjMLRM~9>P0m>%smRsMpJKax7cr3mCYI|0o;U@WO3${Q8 z8gOBPKqLZ;gMXiG3?DQyw6S$*9~`_6D_yB-({!9@xg2L%mCKJ!M!JRHZv+rWv7}cb zFNku8RSvXYlCLljM;z=5_MI@QFpm#nLq5ZjMA#1^Gj?g@AEMl1iOwRVQ|yHaJXN9i zO-gLd30Zvdv$au+Wv@7j3JeUQ$_qscCP42>8Q|y)i9hdZ7Cq&P+Z_I-?xMIFAs?Z~ zDj}loiA9{%wiLAd{(@HxV_1E%ns&?OY+XW^cb)OjC(IGqbtu#Y_ID>BRmR!G_!a%ojTnFnB zXYZH8wn~CPyC0>y)=y&JK2Ozn?&afuu8oL@C3)D`(#F$p=ZO{m;(V@<)kRYlyL7ql zYTJjN68O5ET4{T76}>HXaXEE4y9COXx=h#ba*_v8`sTM0z`qmQ5wSp|Qk1q(Me!Lv zY-~CeU(XqhukytH2Vea#clp5}@wi-?eG-gj2NW020S98pAgXp0vK6|*jb_2_c3|!Z z!;SlahVvlBm}6fwTKriJ?#S+XB3aje{XQM+5PqyU$8oujPGWb0AQb$%7&+k2Zmh$n zDo8(+OxnN`1fct+5c%NRnoG$s@W9DWsR1_y* zG^%8a_d5dmT$dgd^yksjHFEiD2FpE+m0V01Hr{>im|yUz7<-fR`H8t}@k1vzo zkU0}O%q4{}Aon?enW>Q&9(X|3&qmbq*Nv&9v?d8-?x`z3kQG^sAb zt-kZ&VRLilYT$)vkC!NQObd`kx>tQ*&($$|BYY^v)31VBMaP{#?_lDRD%ARvKRXf9 z%VO*;QEkNJSf<&d2aT>ty~Hlm^dhF$%%pg@P~g#D2V5p*BZ+s~a1rBtfMlR}dgNNC znMEQx=`z6SYGWP`uu~OoRP?i)hrRaGd8X>K{KZAPm$5QD9Ui1((FXFAKd4IVcd%n- zp9|#c_j&GM<^p(L1f*fhH1#Q4ti&_zj}4~&co)Xt#hCBd!n5ygIt<+utwal7rEoe70f)YZ!?cmJGioD$Yzo+9O-nZ$`n+^L?mF)wp z&{ZEJX_Lg7+h)>{Q1=Q8Ztu>p?Db z$;gIo>vw&#X?J`nac14Y6?FGM2mUYJt5+kv8W61=zR?$(`UjMU;|2zyzj)I) zo&%6YgBq9E)C?Wks%D8WjUg23DsF`uZ_KnpL;g1e1i3E*!w{zW`%>$-GeI%6GUx)d zfd=EziZomJTpWT_06jcRVopF*-&&j{YPTBEvLeUkT(E68#NY=TJl|6V&LRiz)#;C`usF9kjXU{PLjld1b#gC$2s3n8=t>X2XAqyP+!topr+ zK7~JNn+Au!tBSfwqzu23S0E*K z-!fgqTT-9a)r3-F5Eo24>CZjaI{NcR&&hs0Yl>q1`#CpFk#D=1@bPe&;mF$pEk^U- z@hJw}G&wV#E9rZIJD9a;))-xU;!QNqN(4uU2Nt-niHL~Fs^vuY%H4piQtd_N}d4K%=) z_GeqFV1Z(C2CHoI*`SpBo8?0pX`yeHcfaa4twsMTzw6L=KbN0fOKDSF6U%CNn$w>D zFbB~R5fNyY32WFXyYMw8yANJ>qONAnj@v^h<~FO+2U0iN6eW5-SULT%kLjM^d@s42Zl^1XnnIR=UBf z--rOmh1}w!LDs?lf~@w&|H}K}`nrhts~|-*rX)p{0o*+$TYx{hG@0%1tj=_i7kjT?j9(*wZK7E_xxxT1Q`PL^BM_9(+-hP;LKWJB!W(bs_%Oc3QC|s*(_+9vhO1!?oq1?LM4FZv~*pv9Kr) z#c3i{33n^+9L!}Dz+pZ)e!?EshX_QwE&B%-;SsIj^WJnRcj_Mu z3XVG9fe?DO+;>w4uk0h26e!hC(_Ed4RT~Mb1z%`9&2>~QK(7YW0tVyM3xG|%e#1zL z=ROxqWn;ZgPvLF$@Nb1lFk*5pe|F|lVPO%FYuO2yyQAooja|+$@5FH1V7giYWfaQK zNmwt8oNhXu-b>^}8Fo zo5{$X=U!V%-zpO=)Zt%>YE^wl$n{2Yic zJrl*#pY`HxG*s%(44X*)K&HFUA=X{WR~z42dGgN$tlX+_l%cILuyqDL`m?E@R73yp zT2<>+7DwOD28Ka)o18ZszXk5YE1mNlng7Z0T`vUDcsLRA;;cUd%sN;L^Q4Dk zd*-^d%O1i$cg@|@B|;O=LK0#8y_6%r;Tlm0Eepz6`s>!W07d6rm@e!I^4Yc_mIMLb zC1r?la(hkx>M70Ago^>VhiLqK&LLAn-HlcW6q}tG~Cvugi|$&kZN`Q zh$A|Ee|-4qwgbWdXYxRUZld z6v3O?j7?Scls!AaA-N$wRbq4tDjv%D!ckhpQXM8{nVa4^)P14Adie?2m6yh`$GU} z)zBe3(=5)lK0`7k7sb_?nY-f`YS+4j?Xhof5wlIl11c^RvjQ{4(g5XHzj9V&Sv3`W~ZtH2&&sJUVP}WV&2Z^Fpm9LVMe04{~u} zx-TmI3K@V=1R*1{UzED4P595wFa76E+MRAyegh)S^$kMUqNW<-y1)(FJAHV-ZBNr- z9|8Yz%8)bNU&Y&msK)S!PpQHi09{kk|2D2in7gD&H8<`Z5&hR&OPra&QE=xl-V{+r zfIM$g4M3^{;wZ7|*Pee0UZ9kk03X$kf^~o|fO-Nz7;^Ic6ALih1A^#6PAUSMK0y$+ zK<^yq7nb{IVG!GkscKr-yLksHEvrUii^EfR(tdjCa_7WOlvRHP`OgvQ?vbA_x z_v;Xl)vl`Yx1mDP1r#Hlje`&4fUfy=N#CH5XuQs;$&XJ`mejHOY_UZ(6&ve1tUXXi zZNk;d)-=2_=LBU99 zFo+;OZI)lG=RxKQMz-i81U+ zG8y8mm|z&;!s|u&a)M%OzYQtT=NYfL#{t@en~v0$stUyHc4 zCVt+i?8xZe(=fJEJyZ~Yrvy0aP>Aaq{%HA4WM}y#!R_@{+13#jf1hg5*&xOYo`u+N zt(C0Z3mkCRGG`D^2X^^BG$T{r&r;oiXgAbUukT*|>D!bXy!OiQx1h5Vfqt3pnnoU0 zsPhv0?-v>=2`fpL(zTBo#L;aqjN?o6wPYsq`S#-0WNk7N6uEXHBp!pvlq}o+dvL>@wg%V+y(%}Nlc03x_q=j)6(cH?u$m|*`~h}Va2On>8`iv zZn-ylwW&-{iZ{^eS#%2?a_I5szc`VyX(B;cSNPRmR*pl+Bs}&4QrUxga7T3i<2!_q zXN=CnAv?FVGVqYRez**rR9)8Z5zVn-wWH{}#|P1D0Ua7C61+(V2eE)GrsCI`GN-f7 zvM?<|4R9UV=Xq1AprsIdn6cypcpCw|nOH7`7|q_kf*{ZdSiV(1NhlfpCfw7Drc$br;JKu#b==sjE@g%2iH zL~k_*6IzLZ@Z@s!v0A&abEr@Ur{4=xcuhQ>7{D&tnnc^$Zg-)`ap;lO9AG87juTZr zavKc&R5Db)iP!g`5ZXYa_2bjzU_oYCb2FUZ*X`9G72a3*qC(cdO}UEr31#boWJEWs zTU5!AaxcQNf}^65#2f`~^6?8A$D+^YId^s*yu`9Z4r@nB;MTSc>}!hE9k0o_)6kqm zE2OO#d3Z4?nBopj;> z5LyDF(m%HoPZtCsPq2Av1FG>v`%W2U6f4+{O}C+L=H6eq>l(1w;nLes_wfQdT?!pV zxF7Hl?uM?}O3B*yv740^V-O*354oa`iP; zEILk*?w(@!KPNN2Q?M3r+j3v|XFiWE;=XCeAB~zW=v7JnbPp2agiWZSFNRpOMZg{L zp<9|;5eRTctlEHsM$5kRm%F1C)qA{MDsVLAT+W^uaCc~=W4h1KdtTbZ8eO3p?i!dQ zi|*3mUl*gT{*pIT1%;sqW z^_PkAzJpYMEA!ow9+p|5oEf`~@IF6n8h=u|bFQ5-bqv8$x$<(+%GHCN=nI|L$sT_%aA}stG`6^Q!r;| zOH5D0YW5X(SOKmaGx-w?$7W%XRovE(`6?c!zoWt^@<7M|I(qx_rtt*s63lJlop{YX z8S%>B@G~}ntg&#WOL2)A_K+`;PUMGQtb;p&WV_`mfSC7S2Uw6donBEE?o@*4v3Cl302Leo3@V>Rt3_g}Vm4aBG@ zOzWT1YVtxEQ`Rhw$Rq;$#y>4}gR4!S&rNuL2&RwtKKAUvF?!XOBNMOiuE{3x5;02f zIe3xl!C~L&to6S}lf@wD?WaOulKX*&&ZLtVVkG!oPF6-B}VvC=#A;Ob9e-#(vBY<}3*W>&Ddp))f zb*(5154u$?ydG$R8kr6Plzyj9qARU-1~KB?wj6Z|Lerk5lK;}ozzb>G>~U%s>Qu1U z$#eBYE!I=p4M-dDs==x)@oLJ+vRV*3%y_I4K4-=SfI5yL(Ch=6nG?E6h;!cIXn^GQ zL|3J$p@psdv$u8h3E6g~kYjoowAEPYS8C>&U>d!Y4cGQy^2Z`Cd4+vp#LdEOnWTs( zDIo$4QYE3P2P?2kYTkMQ#}FzNYbm46S6+;0h?3JpNQ+QWAhK(?qzotLtS-WJ6hX`j zSbDXc7m5yBb$oZkFi9I1b`d%@y@}o3Z~N<Iqi(<>N+GZ`b()$oR~1Jy|EH_QMxX8@8h5LdT}Hpw+DlB~!h8XTQ53R$fJA&pA`Y+tUATI4>g*vESu}zuA^g$8doSM8R~?17P7>r zULBnoQY`w5FD4#=mS)+=-}*x6_3T`En@P7R193VTTyObg1}>m}5t{K%_5@u=BiTuZ z;;y;|KaU$RcSAY2c8#VeW*)ec-M@x~fWL;kud5DCk@hd@br7HKGegPR?ep`?3+HW8 zF`%;~SrA`NhuT8ZDy}iV>ApQZjx?~O6WY@(rcokOLbmQ)cgy;z_UO(Nhl}IPwwwN# z!qK}?(-^wF#2dV|)q@&vt4$FDX?L#YyOsXSMt{3x%AERlxaet(C|IeL?B?Nyl|y38 zMq8nC+}oBw`;1Y7&HM8EBgnsWp3{ehH{9qDM-vDF<^OoQgN}CyuIVo~V)xBY1qVMc z$EZn~>1+g2Z9x|=Vi5{lo2ortP~J2)aWjZ>-Bh0_m5bDL^lnKM&6i-Wx|LdaZ~m36}5V{2E^$% zyE%ItSl-Fo_c=L(EA+Jk6Nc$@QcEh=I?@e@kb)!W%6pvf2DyUhvdp@ai!?_cZap`G za1sWxx~Vq8V-oV`Um_O#S@0A2PXwrYokRn$@EzQ_>10!u!)$X=zb5chl+^OJa1%-~ zv4@|s$?_@^0}^p1rDDIh=k)4BlM-6dJb$$hYYfZy4^NRB_Ao7_inO{t!_LyX@)O(- znph`#Gh>?=BnEl;`c#P68@%yRr9GS?@m>#2#p^VD!DY1besZ#gbX9@6yS=gf-p46t z^G>DMx`=1)PB>GUacV(6SkptT;zx{^nRp5o@#)hLHQC~wA7B+z5Uc?Ayrbv^C!ovU5O-3RuBE@k-=8z&l+OD+kwp3NXH^yl(P}x znFoCTq*{9Ni-VMoh)cc#pN1#*Wn$DHAHdsJer*Rieb4K2Abb*N8(mZhGe`_ovGqO7 zFteOD4-V*YODN6!MDiJr@A`$Dq75@Wm;Y9OXC-%-;6@!VyJl~_^SI&368WbQkR-+_S|GN zzdIciij?KI&Tkb1W5p^n*W?6|lNV`^s$wwAhzjxAK`VdbDgol{*F~ui_Ge<|n15 zafKdJ6q4mztU}G34|;rXGU$H#a6_PSKCUP@1q!s5lZzJ|^e5GdCJ`UzIeaB7OvzzA z{4UrGzKhSUlf{jJoM>^W^6&r{Rprr!0dePTmFQGxUuQrU8f(}t$C-MJ)@v5{6z16v zV{LBaL{pWnPfl#e!!6dh(ow`&F}+`8<4H}2o-Hjdh=D*GW68f;d(rj0f%^O~KZtxA zquy0h_TzK*Ttew>@)an)s1Bx-jih^+P~P1;X%90l-h_@nBA()CIfWFA$s7VV5vMK; z4$aP`{wkUyW9*SZ6`E646(xVXds`^;J4~gymeyUl_SZ7K%o)|sBxbyBrBd`@t0B7r zJ*+2v$-|vj|BX^h}rA##0g++e*u!UW}8$_GFa(9rkK0eZ6x0hLCUb^JiUCH zn1Yje(zX{h)}ji}UO9U^kXShN6l(tG^-^iC=m5__(J21!M)wdZ(B)(JCVN-F=jxtP9q+=pQz@JP>gbPFK;eU!7V;IO|8z_eI8UY)ZmZHD>@H?S zkeNM@PM&=dlsfXR6<4)$Y6HC)@muZ(N9k^Nc~h7KCY0xb5dn%ty3SAU_E747E<61X z1Kx?Ev$sbOoaAKZXbRgi?{7_>6w(sAq=SldCrqQ!5=_nE86{GtGXRQ9J@_oq<~`aT zxLl#H*`UXyrbQJHtBF+49Q^{NIoa{U?IF|!nEc||K)n0bWj%z2h)FO^<1u`8=r#Y` zE3Gs)Hs$>wGrkQU?kxXBzZ!(G+M1?R!_SJ$ib$`?Q?Tkt;6|lo|57|DZ5pV5733M% zc6C^6j0FE8NmZ*@%p)Ey<&w^Tp9@lDG$0~GZ|9}*Mh#+qHbhx)H93oArVM>FrXMgh z-;L`%34f-4ONyoe+XB?mG&qlo#D|1w_`wIj{HHH)EiAhINt!dPTFxOL&2_I~r>-E4Fd^6$4hqUs#fr1oH(x6?h*k2Wnkn8pISRw-aN z)2%2Gt^BQ7h$3`fQHmRegwI*)2CZE>=*iz0-OKE9m)qgLzpXlGH}2yhEw!7zAxK27Al;p(hifwD<3_&8WL07y~t zRNKRDn+WlDS&~V|h2OW&EjtA)vdj_}@Ld;~5) zN<)=T3Ep`A%FVhxNzOy4U}?T}xJ*>K!T*xi=n*)d)JCYrbUTI)JK}kDp zrodZ~+1s5xfxRHbqOmFF^Oj5`{Wn_#QUb`hc34i?Z)YrI*7t5l$y;y=?as zpMCAXABNIb-S`i(0{4*xdE4bl$l3<4%xU`jmeKzJRmWdL>MZxAfS0u2Q1V}Pq>ZXG zzSa)4JTG(J9z1>c<#=>E^^ea3frU<;qg#D;2vIe4gr5ibqtELs)gbeYz&kT=&@i~# z-_((b2SfpkxSJH<)NUUYW^Z34r#b(Dfg2zO>oOcPWTvYu5QHA` ze4`cZbN&!O$h@7ygz#!k6Q;9OP7wB;VnTD|G4snvf2m9LKDA+;x+)R7r?@IWTV2%^hl=V_^>Q9Y_Cz_p zv!Z3yCs1hu<>`cuMpxqNNwG>2w}ydYnvHwh zaK;yW_~-J3!2(is?~PkhcMG<}{dblnm!>O`XmPwAq{-hFk1a4E+2A`NbMM!-Lw z!)43r0LA5R_fu%pPX#}3vr>Mw*S&(WZnJv4J_cau54IC`2Y}%~AF{6-6A2++&gNcU zhZI3g92@Leqb*HGjHhmQ)stsd;C}1Ni3wg%!m`ZbN&WNPwyx88;^o7=OE2 zEmn$4D9>b_E%}zcAxgXijY9nSG->mRuKaZ`F`$pUQs_){53@{B@yk;qwNkJdFvJzQ zKDi!F+U*%j@AOfy$n{u8BvLy|53ld-itTSl!YCiUt%5o~Bi+2N(zXQJjAU_Qy8RnP zDO#CkWRY0f3d(Ss4|w~LgNp9{P+HFJvb*SEi0{MW?bCmIVH7w-U$?MuTU^d>SW^2H zq9H|&2hJg@C?D+6rs=#WvllZ|n0!?W2dLr6e7n(E8r8+wiP?4)G zd3BurA3|@{;lZc}RX(vp_*u=CM3Hti}#IBQB_fe=7ab&k99HSa|#8 zBH_fqNX&w9O-G~f+7g1UF+eTUq7l;P=G@rY_M-|V-;AFVpvAlGyuVrSeRBr5+D+ZFR)yyZpt$4FHum8NYC-08f<*Lg!n3M|&(; zb}GxA7ZE$>q)~vt;kp}M zVUdyL(i+N1Y(g@@qsy<)J0rBvItl`19h-Gq{KVKVjwIh)?Cq7O_0xUc68^X~M4mJL zATGa4MiKWhQJDDcq~OqHG&|V1r^PeWc@P*C*i&NhDiE5!Vi&nhQbTSzGTx3}E$map$M{LP59E<0E4 zCDz-nZ$83IRp3CRqECp$_zcUksvi2=y&$cTn}Ig`;;MT62Z%;o8H@PI^v1PuO82F& zYBT=xCI~H7Nz^4}f*#-Wpb~`=dFV62=zU0%BpuuXt-tzv9JdJ(JGzx-T|ECXlrad` zC)iXwg!luS7`ZQpD${f;7_3#|n7`5$x9Tb1^P z-Qh%W-TzCTNcIZ?G|^GogT<+-m5$+Lq?ae@{1EgB;dZQ?fEg|y}=d;&NX z>tJP4IC6L)x4m2iMgMKfhAG{4VGQpmA1ax;M$=E6d-;Z_Zt77=eR~6_ zysVP$b@wi_m}|6OcPTyJI75#9`^=a@ZNBse?s?PnkBGXl0O~8_=)F$oESESSd zzc+?)9=CAB3%%zr3CXSnAg7xrQZ_<-1IKnzo!{RTAC5^HEcf}nnK2HjfwVkfHI61P zgq%V}39$QzcuHv>diY{|i{-mJmM+D1a~H)69|V~@LeCNHn^<+Rr4CvugtTkI8{Xbz!o-`Zpc8f{Le7{4V0Z(8)EM}) z(z@G0wh`ibK?XHi1(nqvZ4u;C1lnpMK{=!E&#H&3JedBTjj}(QTuone3bHBkZWpmD zLo_QpzS{?P9z=j``+v{aEa%e(B8dj3T9(tU&W1}U@$1603f@c5K!Me)5SBFOzS|b;awo+;nPgH^#s4s zkLc?zIV~h(K9+$azqu6^`2xO3GgJmd>U-tm9eX5xU95{Koy^dWYhd5I$hyX95}Ui$ z#4el9Az|F^6th9))b$)650G9>0(to+F&+N(38S;eU{f%*QqqOyFF$wWzq5K?5*W~jw^OZ zKE_>#O$YeJUafiOH*+-)eHpnLEsFaYr+Vr4F~^P+U+@`O=O~@zsFwxi`a6Ufcq_)% z+f-^C0t0hk@@*3tJR|+R8=W&@WL;@i{lU79vi zo4V)rPT=vx0kWO#KP`HwHH7OJtbIIyAvB|F&Ng=&oQgxD8&9{+_Y!3ZC!w+7SAb zY*q^eM_$fmSSYqbsWa}B5Ky$2n+^zzQ?mu5BgE9Xnwlo~f&xFO(QZZTC=zsuBT!Tg z5KZ{9&k6?2I))JHSkdg6)#Gb#j=+MK=1KrSK(XY{Y6BcK#SjI^ah!*4R1vP}u7gwG zqkB*Y?Y2%rY1L^Fi>LJJzlUGHe&3WdU)h~gW_U!45uR3|1T+bm%SB_En{jupnfcc* zMSekqVfiZWw}y=`g2d@+i-Toe1Io(S#gwyPTDVLf`DdV8&=Je7d{5R5b|$rqm4z6R zJN_7UqSC;8;Ey6-woGfO=h<)5pTo5MwPV*SDkO(s9X-)s^nNz&ye}>9?GfPFjXw8M zCz6qMs3wql$`O`~8Fk@qNGBeg670csRbQU-GSO6~w8q2ulN;I5h5NJev$|B_M^3(h zG_r#bWsgP=b_gd=a^(5dkFjTj5~}X$djB;4AEw?b9L~m#`bG2_y+n&{MDIO_VDy<$ zqt|E=y?25k`skg(3?h0B(M$9aC8C#T(L1r{-PgDG_djqjE(Z?gzMlJ8_gcTj^~Q=Z z)@SgY76)E_i|K=^{jGzzi@neF5mnh5UV5_eYK}O5UVfMF>EWWs85ed%z8pE^^5K@C zFS##UOPEqgeG*%A|hvi?Byvq8BuAXX2OBkXSo9Wk?Xe*rN)FiC2xn>7~}RF_E_M z{0cD|KCL!HdP{61y}RL#9ONfqbbfo1W|3NtBm&7qbX9$^^4z-nVs)8-`QENk+WW6( zalv+33T>XFragnU3&g6htK_ooB+?|9@lz}L^X%Aaur66CvVS4C0v zjG^j}mfU=oUK=t`9OfIWnf|AqDAJkIf0hz99$Sc`y>!C*uMk`q(ouiE!?NexIf5U= z?R4@Po4g3L?sM431Gm_x`i0W*!x17(jWY4t+AY@m-=xaO$WSKz>{5(R02?rVVVwX# zJZC~ymjGpDPnoXCPi#vFN>a}K*?cmSmitS-kMpd;@H1_z{lJ|ZN3d>O+STO)&1AM) zuE%^c0f{Mge@E(SA?6F_7uP8aJNgbBR(*aU#>~^WIEk<80Z5aK=N66vs!WoiU^aEJ ziMZ%225oT%BvgT$VGoWrLJp>Qn=J1~q+<%g&X(cnN1CbF?io+E3)DacG52hABwjwD zI#Oh*vHVld&fmssM%75k6APeYBc=9jrC^DRjK?D=mQI@~aR!YMa%qE0_6(JsNfgVf zd{{8iTlyUVejHK+srZK}v0J>lP6o%;sQp!cvrHj4+^bZtofG<6Tjg*5w4cvlsbv*; z{)Q2K;Q@~H-A|4)Md!OHm!Kfoez5jpVT2dpLHo|V;>Wkp!@Z~zo<*2i2mXOmm1~dI z@e2p^&cIv1^3uQnhyAUd3xFv^L@q$^L86CXe90OPVsFAIN}(Lb+ieFxBW@)=3Us`( z`IH8a4zQ$leIdv@eoTI5SLUNu!ZoyK`!AIOk#<)S#R3 z>LjL|qF3=$T!zlig|nl6;q4M`u9T?<_IXB#iEaB>0 z-VJwP_k%y`?Y)wB&fP9Y18^2OHfHmFwoaay=^mdXK>5v#?S35 zb9Y_kj5f&EQB_Jjr+6^nEa)Cbg&US480dVW#|o2jQuH0Kg8Xvc{oT-A4nam^7udlW zZKQE*jkVNn2|E*S3n8DRgNDKoZ0ueW6`iGh%}`C$#C`^j$07sk%s5zJ_|xbJyZ0w! zrL4UldoXlk{HCXJbQHBRXL^$vthMO*VGNPtX#N}VGIpu{o(~*jg<(4-&S(WQY}rY@ zOnLgIrVdmrCf0pv*!@Ei&plel3^fm}8_PJw7jR-xyg^Sfrn?AZu|q%VLw;{gdIK_ z6!l^S&4uDKiNPdFwZ-DoJ)TM4yV*z&0^t-FNk&tA{Y?xfD4(Xu;IN7O+fw=$3}hO* z#Qi!{^gC}WiH$})NX0jGg-kyr5_6g*8X>?Fz|$+qLPy#Y903dgwPgJlDfy{b{^ITlpq{al=L;Fv9ptJ<}T9i zXv*vZ45(HZCI5+9xC7UBgrcL%O&5kcO`4rD4`!N11RU~ML{S>gC{(;Z-8kTW^H(Qd z;zy`U9_u0=Q(`9_B9e)mN6Z(6e#4=)+qvY>0xt z!Jvd>erbQbVS_OMxpzePfI<7Fj9a_o(C*r zUDvdB{1q!({2TbClI43;DXI)f&kwk}ugNE`!z#HTbndoI#P%PGt|+1;!0K6C5c2%5X-EvUJ2O$js3JWqEJdjkN&e4PF~fZ=PEQHr2UtYim#r zz|)UFtt}Ar%n@A#B;ap2f*&OZSpR3iLLpvV^C?h&fMTw_I<0<@IRZmLr%(ZMh;JuP zbgk5<@?ALB&?ZLteCxz)U`{4s9Dowa@R@`>AO|4fqb#b(#J6nZr zFL^Dpbm-gaEXMsyHa`j_VoW()`U^kio$n(tNyhmS95wR?Ig!ZYp_m{h7Vc|s?e#80 zflcruE+7+q@O*LVG$wk;Jyb(glv&OC2A^cKGNgsoN4Bxy^}Hg_7kHj@FWA8?G1%Qe z)zr8N|1UzFq0NUBb>0T9x8Kvv;<41v9aqsz3hX}> zbS4WR&R$y+J6E4d4t7s@{Svz%lH=&$c{6K$Hq*O)ZP%l; zHTHzC^L~ow;tR!B*H>4iL3VyGXD8Xl>zlh=74ldK-sVZANX;m>-*f8{W-K3v8J7>i z7fhZ(l9ipY6k3e?G}Hg>px%P`%{wEL_V-dbSA#Dv=k;y=?f>BKO6&MDZ!QmO4ZcY3 zGB#huZDwTL=EiWKtk{YDgv^X7hp8Ib4Yjw?(I`p|*_a?YZK8;+PE)?2;RuFZ3 ztx+>GK{BGlT57$n1tk}b0$;?P>6k-)J}5*JM9#YfykiCV8a0WE_KU3!<1xOh2T|4` zK9;Z3cjkru9`6C;%R^D0kV8%`AZvED>ff?4O~}7m)Z%1lBHSX$bqQBW?0zjT?l% zB9(uA`&H*PI~P}AzU|W{X7GEYl=5G(#hJ>Hra^-HHnT)MIhoQpbv=h+k3Cj?y7Biu zQpLrJ^NGIuIv?5pJ+gPSphbxqB9r)Lp#?JAUkSpak%Lkm7?U7>?>TbSxfi|^E;4H| zN~xG{2^(A1hr00E!`@b`)w47K&kRB#@w!H#(9MUx^q?`S>9c^tRmuP1RN>E?OYvRe z30$h3`-PbUyJuGe>jv$o&)EeoeU#5{{t0FcUUMJacD+LFda`r*Pbnzz0LAnqm+cI1 znawDOSD)g8W%U`@WQ^z_#GPmX$^xi_p*}=i*Y~d*YNKPgq3Hx(Vj3ZUDKKc$xeQF` zSF0|<@}@Ds%_Hdk1ET6W6g`khgA>*bX7b4E6cLC0y#70^Vp|V7?(weA2C^$~_Z5Fg z6LrX$&;&2dwl|R#?3X@ID-P?U1cB!>59lk0(y*&4n8BXir+;j~0N-^5CZGq!TZF~} zGQ?lP;r-CkM*#T_Z$RoeF`HL*{x+8eS$}MRfx(v&T0@F%cb#6Y%y4UD#7RnAkpw~x z`k~GHm{~k4}s6dLUip3nHF4^VOTy>4%>}83x$1d*Jhwm1i_qR~w_(SXi zBKS>)!a=GUMz)E<;{rEkvb⪼)Xmx@6l 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

N8q%)nN5+#*8-C7-*2Ibs zA|jXj>b;ZC39sKtN#4uh)(qmmy>I%a`0>ZtDs-A#x;9H^&Te_KN$P7JrGFTcJ zLgePwZhnHp@Sg^xyp39|vrXcsNAS^e3$WA+$*#!Q;~;#Q=DQ9OyFW^85K(I+9_msL z#L67e3{<1n8_#Krg*#M0$}-zJ^E6>-kg|M$;Z;QnOQQQVbQ?&jA=pK&Y@q*5g`cr# zrgJz~LRm^g>A5PYeaDpPUkpNg;j1jgdZq53BKCp+`+|Pz`qAHBbeLeAfS-%@mR)!E zGWwzQYL7uqKS9w?mQ?hAUskUC*dp3t!_=3?AgbS@El4@G@K-&8YP4pmS2YH`F#g4P zE|c}tmJ|OEA&|;`K&wEMn)d#X^~wk>ADSQ!Ks*$vrzz4VT17Cvj$FJ*XK7f@^S$_! zMepRd=sWAaEaVz?@bOWZOVGJzJj4n^8@q@3T5=Fvp_QYAO4O{||LK3`G1Eo3arNg+ zHHwa4<&7dIHR(*hp0j8)m^BzWKek9A&I9fQzhe@UJEhoG!*c!o{ksKr40fHr9EY~9 z2<0=;k4fr{KB0<@VM*!0N#Q?x>d==JNRuT}lf1d$rt=yLVM8X9m#Q zMh7!~z^T$j&zCFGvTwv}KQ*;}bAsS!?MmM(z(+@Xd;|U6z1`d{_fhK~R?%$v0z?62 zv3wG*MUXr_ehD-^SmK#Qxl8ag^oqyTok#p;H4#oVvA})g#%4R8jT(%QV|Nm$yd!Dt zpiQWjWjm2`d3F7&*`)o)6r{8HNEo+y?I?x&6m*p-oYSA@rUUdN{%YH3+Ci6(v&se6kB^>Wlge6Jxt-hI-SU!3=Yb)_3?ZC+; zCL`Z-e$2j!i9vLC%2ZHVJWc6wOC(pn;ikZuqB`yuq~(Py3%$o6bOLCd3P_*Pc1Di5ev+r@<8t%@QePqNAxQ7p5i`JLDZ8xt-&o- z>6Q6te<%Em&fFgU5jR9}f$GfpMsJ2l!^T!vPU-3#k}>bywTPQl{nv{#2smLGfTG*R zTU$S}W=(4a%CHiQ_eTc&%%{cVA?npfZ#mKaRGhqPSN0XOI^uK0R^F>-lB(upZ_Ri$j1N*A z)fn5-Z}*;E8Av-nW6LRiGZG0})71cTu5W0~ZG-mnJL|Gz!>6>z-(ata;?7Ch8rR*k zmqLYNT%2^5)dGwm8K^-Ts~mMsh=dw*>mPE%gqZ$5(92!al|6v@K%&`q>?%66c$X9` zXQ8D7W6R=#q=I|yr2J7of`#xZ?1ZkOqLLhyDa)Ofx(a)={77mxXuc_QFY&p7af@>` zxl@+j+Tu|&(wT%PqtE?YpE3>6tp0!1jQ_Se`TNre1;riKB`Y~MPCpi%;xnX z2RQ-zpXkW6kwrPrC+~^ znWz6^JC1zQoEW$H&GC$l7~36*{oE*`i2>7!T(4hq?}4F%r2#^* zka>tFx$|*LH2yt2z&QYDd&CD3ajByGiI|JZQ4ls#e_Hi@bj3+B z@90;d#mKYoTcCWUOA0}2wgr_xk3!3Zlfde)ZBvAyzDK;i__UWXHBAOo#}&5WuaL*? zMS1X}nqSqVw;%k7(1lAd{FFcWhayZPbOVwzv<#f36kM6ZJU}{>EmVsXaZf)_{mKR6 zUA@S36B&ey7`E+43!nZWk9vS^Fu~emIP2oX`CB^(S!90qvT+MzV;~FDW_48X*J{%43nps)YlU zM?f5Bm2*!eOK~zf^B7x|yRmo7P{O-#qOXG0YG+^yu93l1Ja>XPLUn`Wx!DUsP&q`( zHipC(stQOCFG{pPdLmZjI+`K7Q94vWox;ZoYsbDd1bv%xyWfmNd*z5f}$6VwDI$IaYYR*xl2DgtHl(&Q+v;!IsI70(^XiV`B?7&3Ga9{Fnf;F7uC3u1X z!=($u0sf@C*uWY0Y{QCwI!(~GM#F(gjdSOQ+@#RqEpSt`2LFWJ`r_z+us8npT$gHO^}CI6EjR)ZeYzUi&T zrt=ENeLj{Pcc2_0DN*}}xi=A_E^{2X#cMuOQ(7kDn#cgBDu^1axG;B&3q=1Uc3t=Z zW?w(?6!^u3qx_YIP4J>wQb^r;l7du4$p=+Mg4gbD88_jIZWQCK78SibOOHiNv|Cb8lEQ8mWmep@2=77g@oIw_%_?CU(1b z@PYWGiJ#iN8LU4sixqM@DZR6@h38)d&Hufmg;P++q>bd6v#y zkdNnp7#AleJ3HUK;_B+^`g(qF#a+QrVaf=t{{s|^jKkNF!{q4K7;4B5x!peM;kSA@ z4^y4ov?^vFH%c9aeP_6snVE@?f6jVJ45TUqBO1_uHLiTRuFcDvh<%30#8)?*zM3;d zg+L!1wLHb0f_A@`3=OY^dJGNZ72up9Pu2RQM@L@h_kx^m0=v$>up?D6b>&R%K{a3u zcr!#xJW81NmKPqAq*U9j(FJQ|tt+2agLLZ~xBB0Lh^*a!KZ<1JUl6!|VRzvezD1yh zHp^bn|ATvaKgH6ZrE3XR>A4oq-2brG=9h}{x4d@G3Spfq(s(Hbmzh*9B{2pB)EV&Z zFq7!PJeo5X7(ToN0#&)}a(*!z%IP+WZ*Rf1eTnK^k{*bLPUq%+h)dXJLc`cJ-hRJ~ z@QCpN5)C^aY*4$3cEX|{T{yd^_$@#5)&cB|7vX(PJX{fZF`f3x)bvnLV;xZJ*3+%R z^KWM@25)0z4E_T(LBiRmrx+d02Pc*P#Sm@8A0>G&6R%LDUDG@g=u()Qn?UUg)Wh#C z=r&r!j{$lB01#P&rML+6T;*?VsJbCvXMEB>MYVC>-01VuoA_aX;N}x8E?5vWpluXm zYR~=*!i$pM_JyI)TFA1Fp2+A4z6s&B=ogtgQD*A|Ku-@hFE3Z$fOFPzD4l1Z!S?OF zwIi@*bL7`JGqfUuMjJ2XlhH3l?KfaLpw)~Y%d^$X%F*H-sV-d~7_vkq2Dzry3t34o zAy6V}ZZ)$O5m=sfjbV?Xh@R9~%zGhAf!zxmzAQ*psV`GfoD>w6pvcVJd?`koRVEuC zOTszy)ZT6$+$Ag|Mm@*4XqByNaNg3)R3x}g+}%3{Lv()FpC&bxwLJ5($`148(liKqsK$JnGr2`f zj7Xw7$C1doVTh%QSTPs)Zuq=q6gi5Zk&1|Rd1nDJOx=mnjM?cu^2Gzt3mBrm`6tN3P)@Hm^5 zM8FT8l=80;XJ#XKA`_(^=S$m3y7A%9c)O9Cs1a2KUBv5ZBw!uD$Kmrt%{jch0mnq` z_ql5>Y4|38O_j8u5p#okq>%5(zHs=Qg0nrT(GzN8r=dS;{(1`{UbwH^+P7ZqM%yLZ zADy(!C+g_erOU!_nwMXYnLanvpAqerkD$H-6o@Cf@T1Qv$BL2p=@D`scy}c_yCTl?auFZL~k@#}s!4geYO-4u-{HdHvY~ z+gM21sS1C1%vjkQ-Dh8z;bZ+o(tJS+gm{>c-1T&Y9M%Gy&8dNpFVhnYrC5882u zLlN7QR^M%E0uFY5xYXGj8|xj47)ep}_1;5daxgUcz5L0_oLoPG#wh1HLLKL#xfy6R#!#K^@IgRFREJZDYx{(GQJcrMXq-1YHD zD!!F(f`uXfeaA#NpQE%dz#Y$-P0;sJl+QDB2?yUQag$NK9-cI)Tq+rJcjB6klmS!0l+u4QcH-j5Q(khL=yd*aA6Ip~)(R za;mb~T$ki=u|!mD-u1_{xjsL?{x#uVmb(_!)`qDMnKYRc8;}_OVT`bP@klOs#v8B5 zdghoQ3%h>Wi^J@3q!-aP+bIuI>qlf*!PaJys0S@2mFO%*MkD>fy_%h@zu3=ekpRwi zYX)ZWcViJm!!GkKw!T03r{13IT3EJ-u- z^L^&+Ui7rIv`!RUT<8${H(C4ap@0?ZAGb2XGba(jUC5ib@`4S8yr-uy)gP?&KdrJy zVz+9Ii2aXtZ&D9ZI@$BGGCq9xU>H&h4@fw}NxPQvR9Y$iZbyjk#vHT*A`TZ#3g_mC zj(~E^d~NQ>2JYIDY#CX4NkzzW&>2Sftr80L;aVv^+wJwYeb#nUMJhxrr6GbyE zx_QHrt!vEM#+^~CoBrZ`3&L1hZ8CzSoC`Qfa~zIrqWTB*@ll5 z7P8t4K{2`6BDuBR`rd>}+B@GYuFd}-OK+Wu(?~@2#1`rJI*{_E)Zu^Qip()vTP;6m z75T?;LpKkb@_zS>uLtXleHxV>@4YSr58(vJ80_x$X z@m=Ax{B2MtSF+ctXVR7}Wn)0_DZ}a3b&(bN<7oxj2h`c#57qyJCUOqsh9FHWH%^e7 z90Z8K%St858nmS3OX7*@&5h>Ztbl37+(0@eLULhXws*kW@6b2f;Fig#BHFM*`LJn} z1h@xQ^Y=H_9fQtPMAtB->l<@g=5b^!%q`3Z8{$KULH|~d@Hx%yE^EGnGstRc z|D}L_F!?UwVd^B$*rL5 z?T_=%nV~N7i7P*@_fe7`QU^Ysy_I`_{VK&Ii_e%IAkqBudxUu0BHY`Bom%AU@YD!o z6y^?Ww+u)K8!UG7x3tm6(PI1ax|F}oi_{9D4sdMnI}^c;lqOu^tf3402aD=28!EFv zLVTcUt?@hRB?C5Gm8oSzP6}i64n()$aSBE~J*{UtSVdxR-NITmHGfOVH(F=?#>U19 zU_EB+57H-W-$BJi;!?h6Bp#^JkA^}$OMFS}NB2DeUo`FeG|24mSU{DZwQWeLEs)cW z2P^^2tTo-Eth=S0e9LonIYbhu=~$^eS)B-a^M)8L<3Qh#Tun92kGQDqiipKY&A1Gt zl9CjP#G?*Cs(GXrN#_`65DC9xN*QLVATl&TH`&U*_7tf-pc_(ZStoLuZM19^`F?pM zkE@Na5~PIZe2C&#H?F|8E#DTrFyQ2~M-vAQrd_sW~vqTGvoe zr_82`x9>nhk*OfHd@!z5kB0}MZfd;@O1u0T0msbN*W}*=_w+%BF227`snE94``~l2 zLmu4nxUT>IcrUc{BQS6yAHB;6GVZ!e_xV#Mq&Q50SP(sW6Ks%G(+=9#X8(KOT5V=v z_9;j(RwC$Ab|QL$DxQJ>@cpN76*qJ}8Ft1UqZ{BH1>Xcu)!RQ~fCC3hb!O2&Rp&|! zmwIiAT}ca|Scq5qW-c$svdibt&(3Q!*x`l-6M^N^&&XBKJ!?hd+5H(EYB~F!tT3SO zwR3C|P(D{N9QJpt3#!k}%|qdM9F$D2y{6Tk!>xP7aNURqlXBguYBKD z<_OCxe^`1qk)QEZ+?~~`6h|U$*X(IVksJ`Fg(8GZ(oIY-m(;yP{!lqXg_t}~!(l3s zc?%aikqINI?7KDF9r1*`vNN91yu4z4fT=n+hdE4=lK}xMn0T*U^4Wgy`I5O$A`8!+ z*%n%U&ZJ^-Wukl2TC`9$fwh!5&Se1lwgb!h>M;W8?18fX25@&de8WM$E{tCUP8Y?GuKwcD5tg1DArf_C&r^`WQ2h=)1y*nUMoQVc{AS zq_XlrVUe@mIp|+7Uj=_r;2Pj{MY&N@^`O$NQPs(aJ#T6+$A2>LlHo6(V_i> z1!C77rq~@np@X~ZzW&>*nE#cWDjk~%xi1BQ%G!>0NOXpqZ~Xi&#UDS=b;^t-?L6Ci zQ9+uAfMN@QJ+H{b>CZkV*lKP;0w4ZTz&= z;GURT$HI?7%Q*^W`K(~sm)&*OtOO!2s-c3q6~N@?P)=ZC>TnknLxHrXm^&-F_;ZHo zdc7$zZs~XerZO$9;-E+uw2CYi4$93{?8TqaA-seKWu@TDV0vvbc3s1Wq;bnZvJolm zM_+FS{o|3XBx4??S(3sx@1ocX49WV%3|*oiH4!}r^x zL)c#7&_5+|RM*q2p@~d2BZUFv)LgsYfaS5F{b==Ax~8@x#zZt#G`bvf0*CKwdWjYm-4e;SmXAZF zm;BaNzXaLDUr2DggXJ+yHh!R4`TWnKph4 z|9nZ>5pz(Tk<)+`FijMpova}L+R8M>cP~!^`v!~n3$m<%MmpdJL99|pcE6%&j!XR? zlBOE4sPFMvN<%|~c)%S=RL4N#J31_Nv!~hS>k??>Uvq9{g^0*b`mS!T+${BZ1L7fo z`q1_X)Z{lw%aIelSTV1;$+h}o-E&Lq`6NRww$ELWLhqAAifEhjgey{8(x7Q1*%d)`Hfu6b2XGwS3O%g2S#l>MO zH@v%~fw(19YDOOjDzkAW+pWu3)ElZpQ}>ps&{ z+)VXV93IVHhy`PE%sm|69XR|~&LI*{uUPsBFs*1xJV{e&M~kUa{2vcY{xw%+@O4d} zxT7=VaV5*l_hYS1W1#ywyq+h4H#f&ohWpZui4&dE8?0_fa`@bNg&}$_bdNU<0A;FM zwL4g0So9bW#`IsoNCP$Wo3YmKljjh~U!`>OUU&<<((A3shdQFq&B-x=6_u{6fIAh1 z;6AWgWCv+E^sUeECi?74X$ciO*`67ru0v*nzxjRz7*w0iR|W$l0(^5TOC&K7+%cto z%JkSFkRs)aT@1=x%|*G79v+TEY>Ep)p5eP^0UUv%4ewUVcQ$HnFA6m&8&4R4zfHIH z+H;DLdHZXc+a(8|ZPW0O5!aX;Z~x?=IJIPXICeL2r7}mfm-_3%@b9_Q4?Z+22295+ zI#En?pIgO@5s5wCNv(ej#@it&;?+__Xr{3UzGHWvq;oi_V*rTEPfabBy7+Ao@qYC5 zTT4;|UK>;-0T7X?hM(E0%3heptl@fzq-r5Iqg~bUKzqI1;@)*xCIa$D5Wb}@2BAMF zxrXhCIRK}R#|kRJ=YaU5pB9sR6Lh=)M9?CI zA-N3{F_ggUZ^_%FHjR@%_mxc$y?Zyw%5bU0P3|p6P#9Cw+_IIxKKlpPTx82A&|mAu zeuUQZ53uL7Af!<}c=TfG&AZ6&ZQF5O&)8mMyLjF`yFI;G!NsP(v%8KTu`$1qLOQdT=f{okrgU_&p9QKW)T5I@~;Sm zg$~uh?L3wQBh~@)zlx;VZMmBtX^Is(9L4>v2=(i96tqx0V*&Wrr}`C#YW%bSQA0yZRfLn0m#YxjZW8Q>rELBqL##Nt+R)<4{57og^Ns8zyZ3lx zYipCn^_RL;m;)fkL{IBDyh7fWB_$Yt0eVQWcWr3LS?+9a|0&YrGoHs;)^M@8E7Ji4 znU|IAGDxj*W!%7T5rX@1&iq%@-!*lat@e&VnS86}>DD_Gxlh>z)~^d;WsCY62)@#@ z62A2OXp^=I4fU!Yar<97x_X@Z`i(2ElKhxg~d zOi9Vl|J1kz=W|rXcsQlGKXt5HPv?Jof8a zZhm*&v-iDn$jvn|^CZ}~gE|orGil7L_5nw>^xN@-x?%~k63o_Lb7LaxSmgL&H!OYn&aayD~MK4aqi%hVuD)n zfPLm3y#WqRcS(W=&#~z#geCd=l5BE~)YXSXC3bClvRh->*hBuTXHlcie}nL3-!8W? zlAqI>e0A~GZ&iyiKI7)2+0hrd9J%Fb7~iPqsj2BbD-;5B=Z=-ii#QX10(?<}>Ee^@ za+=9D9ph372U!Bli8^!8fUN% z70c*NFOoaP%nC7E9k+}+24vYB&u=>kEo{)t*L!v$$k$>!we(Us5I%im;jbD2wX=*n zsYjaEebeaH%H*8x+jIP77@1^3f)+2?EZjTmEH#}cT5VH~qo|qLgZ4~(z7O$Rs>%G> zmm;0UsHJ%+Ry*HtcgsP$rcB9rb*e2f{F0HIvbHV(cE@n1V1K=>uEd=ajvz>K$}4xS zuM3HE@2@HNh;t3`)Z9%Wng(yHa}TOE{72MnIN_C*DVHzE_@`8kzJ@qQg+Q~Fa?Ne> z#b3uzp9?z)NQq)=KTs6)H&Z&V{`v(RklaTLI)=0$2|0DxW9w!6fRQ|KEsgD)mHn8E zCTt4UnlHls37fy@gu}tNX(vRRe~`7$&5WC?8^m4pgmV3VA+>UXnH+q5t*D*1WK~gO zu^&5_)4$anCbqaLAo(S8$vQNXK5>$HYAPJwPCdyTkGZ6Hvb7uMC2u@YbSNxjwF*oh z>Y?^>s4qLJMPVr3O7ElJQuGr!6~Ffz<<$ydj7y}Q}mMQaMT&HxdnfRo{^G5;4$1|S8nUCN45b8NC`U*Fd8fs8 zkqwcFN&5k3D0JsgGj5ifk~Xe54+Ezjx*k%uCf0O+U({uZ16eXxlfEPEYW7XU$Paf{ z;ykbo!m85LHXd5|Zp^GiWc)4EbN7y&oX__Ok2)`=JlS~0+)uXI1@BvuDz8NtP_rPtu_C>Np0!tV;PS^(jLPGiY^ilK_iJyD(;m1KJ$Bl224Q)^bmCeOeIRtaO3*bMzk>|!k7c5((tlrOx>|3|b z-0pR*S(}vo)^xr8oEY`i&+wb8j7;9w-rFBqL<2g17ToQp$$ix#PT65JXbQh|w#~0} zvs_8=1a;7CI+g@;$WIwmG1fX9BLp>mv)40l;F#B-E>&q-PQ-xRGV~QK#x}YPPU$2} zk~I*JeXXi?VK1kiX8^pI>aiqFRVyV4_*}F3WlIayZ*|S(=R04|;f?8#Vsy)I$`R#w zcg=DJ+hm$Q85zDlUQTt8XD`f2Ta?zwm4ucwz5vPm?U8=|r{w$F*B`Xz$$yUO33o!YaoEMw<9)uYS{Yiqwf|+I_0>x8aMG<8W)pn*P}YEp^MZvfHNbiGl5t%|>XR zz-rRKYr^LUtsaN{EDxW-?`mZ!{Y1WhwmPpj_aHQs`Ga1v@q=y8l4v;4>1-Dfjy67Y zw>XWW>H#i^FIgDh+u1Koec2>E+}nFjnfF(kx1Hv~GInS?OICA^>8PJwSkC^p_>pH8 zHXHd+f65NK*pNk;M*FIyXbF5G_R$feq8o3sT$Wv)o<1NsS-BDaGV6#7ep*$V??I;a z@(r{T;&AX)cY}1v(yLh<;=A<>r_DLo^M&~O^;Dp$j1{7T@yGq9(Jxz0-eVWa@qzws zrm!;BKkTDbL9BIIA?f)I_BvB-X|}rt;eCk>_!YqAP$g2RI9l9g@ju*w>C*FzI~sbE zH~Ih0h~xdgv*uH0-#Hl%rEjS|Fp`7N_(?tG?XVjX-2s*+*{;$FyF?)qPwqADZ}NHu zu8T4gYueCXu}-KkCW7;7X%oCPciv@AxvHthtz7^f70*YFy346@aWT+%0_0VlLRIXD z^R4nuSei&0zzeU`B z(2s1N4k8V!d#UM%`oETao%%q|-HIDl%nHm0rab)x{`m|iE>kp< zAcOV#a&w6IG{tXKnusH)XtkPf#xc#9qT;TO|y%?%|%n9ltltcYnrB6P4_K&R!?;#ZZ!x3RIY-03PhlA-4P zC5j8vI38j&4ta=Ujv8)7NqDuRv6Rd0Vv#v8WhPTiaZX;$01HP{2P<40VN*z98E;hw?IJ~{pQK1)kt=4se zbsE@cGrumuk)8iSdMo;dn;_FfIt(inMb=pb8|61}S;cw%^Tmf9?_iUsSJy{X0VdrV z0iatBnQ5eRe9`+7i#MO$7t3dYK&1bxX zEMMx*|6i5=e~fOZ6Uj#+UQg<@JH;@hLCQonnpuc21|DqGtF)&i@^qr#oRk?Atoi>+ zl{;bgH%zAcE%x*#m=KMn;q(yXj$S8pWnjPq5DF*;(_WxRLH@|Z7p(0o8bhU#Dtlmi zl`P;;srB+ede%*nZ+kNl@#^+B^e8H9-%8K)db>XCqit%Eo4hLOr};`S`+h{79P;pQ zc%h^31Tp=}_R!Afq)(pi?nk743TeQ7K&0Zl2pR>Gumd)L6H1Kb%cresgKN;}%z7)q zjACwXZeFTNZg*pP8tA#F(jsk3H^yhv^&X9LM75|0UNyIS_1PGyfkw92SPp?7D>Tw*7?oXnmk8_D9&Pxm>&>;jtEbccQ<{SD3Gh*U@X zJN%p}N^YsFd(3i8yxu;{pIxqN=G0WDLsUZ=<48Uk!Q)IB;^g;zhg7l(@7I2W`V&5*=3`$lYmnFiPpf%aU^Il>_Fu6FM*2Z z9nAzt@qGLi1{N;rY}7mC;d)t2$iMKAGX(f^)OGL`3S(>NTZ(Lni;q zBas0J+|$0Es23-Y&a2(G$qbENPXa1piyL)>5RTC29QDG!9aML$tib_P=WBtZmsjn5 zeUU5yJp7OV%H`OD!|*wCzSb@0Nxk^x8{=0WX!W@&9w?Hj8(w65R#$IqY^$$rk_Yv+ zacns)ZTl-V{F*dY9)tgNPv{?tjyBufc0ilxHr7`K=8 zLFpu?)g+0O0P{AOb(`PmL{t^_kgc3=RSg=MyhaTs`*7qOmBSt~l|CNsYYu}K1 zq~rAzOSebI=dEv4UZDce60zAJ7GCXSRZ@c6l;o4|cpx}2qFo6Cg7}Xq4uJt#h2Gs9 zFHhXxv^&u8!aJv@PEo#{X!Yjgz^o1iBo{rn(%e?)vY94mFgk!qJY7|ulD-Q{+yv!A zId%5h?19O+te`QHl0qn2G=!6DWN5V7TH7x{u0pE5>4=^`mO>aa;K$WU2Ui_H7)6>g zftLm23sEy_`xKBFjZpccRki4Ds=cjM`?Jxzuxne_m5R%cd|n1VO-bl# zLAc=2A(%$~6^RYf%^Yvbygp00y%R}crNu|uO#@*o6XMd=CbibMOKp$g*bE2hH{=im z3ZE;-C%zye8agzV5R-ce;#Ww_iy|o%YH;46#z9tDj8P~>VOA2oCIElV$@$4LmyZ{D zw&q{~VJ)J%TK`&TrpuJ+H*VoiVKGj^Nrk)-egn?Cfl^H3yo1uP2w5?)zmSY^NEVzt z7p5VSluEYvBE3Vg35`TErn4u7$`8)*9s<)2dKwHeXX#VEWb>Dn;PScdXrj_>v2Lb& z8&;<})!TKPi*-Aci8j*c25h#>+ZxFe-Hdc>KlP9SV^p?f>WmJ(@?J!I={4p7k?ux|3To zNqpZP8u&;=*5<2}h!7_aprY4Mh1nPAypQE^B~vE&^0Wz#7xbheO;_g}BZP$D@wY81 zj3mZc@;t+=>J!SuwpIw&?knFl4k2<8Uk=-ph_HR60N51imRDLzx!Z+ET0vl#*e=2} zzSi27ukCuhIq@z%&o$L(Q`Kns z#cAz75NjTtD7rCZ-5g$H8wd##m*@*l(aTOY{YwuTjun&O7mGIfg2q;U)R^6WMq9}h%_nwJ4egyoib{pP z&kT^Wwm*a|KMaaXEl5q27>9^TIjsUlQyD526ZtYP^SY}Cr!kbl6!SGY}6FBZ$Vzk3K% zZW|@G0u$wH6OeLqfwZs?Ome$}1yS<3vMoglQa*Pnbco9LmAKk8)fZPR+}bf0S8H!L zWsf84pHy(x`i3fR7d+iQbZ;Ulc2iLTir@rf1o0m8xxdn?NmBSTQ^r z%>0TycPGQl%Q$(SqmH${CLEB!09gIlY zRjx^wauKB;L6Tw@y^T*l$(VnCY&4-NkHf4!Q=GG#hxklYp2Qh|Jl3V zAd7Z!wEy%ea^;sYJ@GM+cEqqW`HzP7>#;zOf3@8%bRM7PI>hN27b$_Bo9+jj4;RSud>z_KOdjLWzp*+ zH;;GM8`$^S*VA5YJujus&FSgtDnlLdzYWpuP6-XQ3mI`&c2ITR4cKzdOLxtq+mKj* zt=})it|u?68e(o;usAQLdaL&`=S#Opn+Tfjm)ioGT$`jt+|AwWp+V*p)Y`SXPc;(b z;!wI=5>YnYnAHGnU|iHWMpXaf~6 zbb?g%0rh*+9Sailh+(Qi3VDGK_s2mKWD?Hn8-8j2|It5(A-5&l(d&<6%6n^aOV4Q1C)g2^IDg!tL}z4lveqt+R!luwc$MVnh;sG{cIXNb&EYaKLi<-o-K z)Fm=})qxTFZKqq58AYk;vPD-f*fY-T&mf|YyiW60#l&(dzheg|i4F40^_T?p`z;~V zFw>eTN*1zA2)DyRH6HMT%6Jnqo7h=8XKe0SPSkLGv6^wJ#*@ahsz?`gw&}yKvkG5t zaZ;nK)Wrn^s`h@Dt2#J273V!YvES0-vkStZ2xTuIlR~8k(UfXbRHS$Za)@B_pDS}Hm&T`(VIT<8`)wLqujM-mPJD&4DkRB5W^$9;|{9sr= zHp^zXufZ*jo#!U=?X`)Tv&}UHrll2z-sA==bsAe}9_mQ3!;IqMD{1}!@1NW0bS7id=U(OU2WwC;P>T%c(D+`_1)rGo~Jvk3Ft5IHT2ye53P4^77@#desoQ$ zzR)v@EfmfMt&D9-#O4NsCmZ4kNu(PpyfC0~5|n>jk=RY^kp4S;t$|TvnT*8~Lb~2T zCl%&_?;>7@#F#g?(1!{maa}$sTp3ZdHGcaRk#x@7dq+!WKh`URQ>yt??hvqL0yNS~ z{^aA+(9*&&p~(VrBh;4R=P294`{Lqw49pX)3yro2gE&7(N?{ci)l>U`wCm^o(NpHd zxb=SgxX43dkX>b1(v;W*Ax;J6*1eaqfc#DQx$K~IDuF1Z;tf0a>QA1Lf#yF5uxHX# z$~J#n?`*Tpw3PY85J~oG#Me)x2Lu%>T~K}d$g>6Y^%up$IKInv`Y+Y^o%$aM@8zCK z`@~2F@a6^|5AqLfXkh94kBKfD%xoghgMM|65P|}Lro$-{=aQ1Tpv=S*v)===gdnub z0r?w!b#8)1GAgc6mpZ>nmj-Om)IXAagX8uF6SOyx`vj7SZVq|12j*~~b{Ky9El!0r zz~5}0ziGO1)~abbD%7^eO-;(`;A||23d;9)A2~9bo>B>9~?cI%*KqE;bwS?v$ z%|((x;bWtc@^e*gy&@74NY#q!FXTD@1blrov=IDMO_A--T76FWAn&TY9G;Ev@y$Dl zp|c6S{`4_L0nAyYHF`QF- z@kT?lR`%=Evek2MUv|icozU-_!R+*S8fby~rqcK7e0fcl2m^02{IqA<+I{**WbA2G z{qvJaeS1^PfV8HRqgm4 zyDa(KZv%N0>kQ&Uv;qN};$<`98bG#nV$d~lLNs5#dIU8oYIjGTtaj6%QU|~$ zJk!nHM2ZG^C^KVJ$_Bpk#v#=NlwcO5a1}j^x{X9+o!9W#Psu9Nb2|-QQRQb$(}>Sw zBv6$xw(A=(UsRB0!LVw%1Xi-?D?H zANqGp?Y;l;@=d%*5Ip~Tc=jI$tc%(q>NBJ6+WES;mdw^AF4BKF_9@+Dhw}E zZDOtX*=yqnl!Me5V@Ha1a3a$E!l#{h@h<=(H%zBAnL9hjYsCSHM}BNkifERktHAYr z%TsI04=*V~=f@Zc&NN584|6x}G%DQ}=C=|z28n+=yM9yTD*9%??`IV_Yik-Qn3(f| zB&;|hry)ik=?l@}s%Mi}d;Rqnp-mc}S*pm_(OFYLa1IN^Dl>9T7loH8IxG^4TWuaf z;x_&&j9-E_>)Gfd=h6?-x+rpiO6#Qk%n@~ltU5Z$n@9bGMBtt~YRNqazvcExUv zVH2!OrE3bKbReTGvR@4mq~55Dd43fPPe0K$0-QcSyYFMa9xrasPf#1-hFZ?5#=EdL z+ifv?Xit<?)j{G&gqPNKB2lZa~rd0?WrN^X-~K>-I#n#bDDdskEA}r~0c`MJdz-TT^V=xnXUr zKsISnCl4X+;5&WB;O*@V$3CK;3tefG<@x%#?V2vgb*`~Z6mpaC(yH3;V#}$N0ib8& z5|mH5r&Xyk39G31__OJK-k-hs`DA-rZ6`lVLCUN8zHjz9LVHaKY4}Z$`Kggq>V9Vx zuaM#v9PDH?K;Vza?}S#}AW-D~l8ic7>A$zU)WFc^PSIbGS|3^ltLb zWG9q?Kq?ZXae-%Ktp_LH|4S^c+Ww_A-G7GW0j)vHLH--kQ3!P2V8 zlK}fIzx0{&QaR+`U!U{qrnW}i^(dkqBi}++2D}3ZvhjsYh6c!MwQTw*&T|yC>&7Mk z3B%;uIa4hIKI~;+`+@WF@*bmU-ajYCPgk7J%RKT=G?lkfDvS)A76U028Sh1#i*%;7 zqc8zrfXHMg&$7pUh?JfcUEPpc7XxvL;HKK7XZHuHK}OywIZExGgTE9+oU>Lz&FZRf zzcC9YM|Z;}j4R_pQ-6C~ABslDwnIq^3#f~Ui5Tl8kC_fjA>T3#qNkwV*sM4z9_)ra z(kP@a(_zfryLV+Ssi1%PgR62P`;qBTG(t_nzl1J}}*mI1NXLMMl9n3Uzu8e?`ew3en(e-tIZyr^&>?0&~W`A9&?IDxVha zk9VkcK3N`7kh;oTcwumSnVp%N+Vh!4^0zQN=qRjjh;~TC{rvel^3~j3_kr-CAV)=E zRz~YV&5!>XIIF)NXa}EEP0Go$U?iFq2>LrkZt@a@1|2)N|8w!xyyW#H$WR&D(U4l- zV9u~70X;sbbEI*tUvD=e0Zvq^E}55Ss%;4 z1wH|-k?eteF;@KsGz;_GHjKj++c+9e+5)co#cm4FMaWj<(gJ;a?Ntsn<=NdS23Ik) zTBU&!v(mY2udR^VcD3c_#EEHOu}CezV^Ki2Au_;ab!rInF7aDKpI!D(yi{DTbJ}-t z3(La`*PK`?Y<$Boj}qSY;%ly86GlpzO|g0_=II4UC+2+FL@IS2S+6*O@3Zp zvK@0R>2uDDFiu|z(e4;s->?x54!%EfniJ&%i*Y_~@65(`J3AR3Jn{fz?fkjKNR9!H zIVOu?PA!Hff7W{ZJK((x);A)wfAA^{&41FT4RCH@R=fsMT?}po%XCGg_$8dOabF%^ zK5ouZ54s5I-GZN|E$c3+9uE*aq>?R(ad6x{MkW*G5{Aj%hINfi4U?N0R`-Q}`65$j z))MWHZV6%X5kFUq)OhV{Viju~iA9_p^A(jc@nwn>_*A7Zwl2NmhgUjAzw?*0?8lo{ z(Kbxp588nyS2vV_Tchzl`%^Yn%Os~q&a+Xo)#Bw^ zjuA(;?DZB{?W0)~A>7oMYA$nc$|t)OI=*Qjq`RbrJ8M7)qW18j8rqrs$rhBEPDj*b zN8c4XeOl>;1f<|MNjG_35e-H~g~y0;?AOdyh@>DdH@~p4vTZ34%1R&hYI-2l-$pyT zCXePc7&-;J`JsHQ#r<*;q~c<9_F$#)o*QrKQ2`u=EXKMvxgD2@m>wep>5^OODl?KJV1^CiTokUHUH?^J(x-b<24 zM2g9()zv~e{=>*uk6WfLcAyTabHOZJs$lSy{CG}YCcK82`7kLTig1t zZY?O*RoHZ&JRc7MKJ!IqGvp&oE3$auqPJ+k5Iuxun;bVc!=@@*VCzke`x`oFfIl8c z!mr45UoRLrJ+NaMg8`{NI%-O+SsIu%K&!fqxM$Eho8cRTH3C5lPwCqPtCS{jH-0g- zZ-e9JG^IiTo+8nk(?tLsvy zBdLESLk!RV9PX|LYX(MSnru4)3)#|Tw4Tp|%N2UR=+MJb&du=|7YTa*ok~(67s4(7 zrq9Y@F^3#Cn-5Mh$^epEy;QAMpdrrm6usFlOx6q_=~X|^5GdR;V3sBUG0s!G-KGj` z$AjQOe#$U#GG*fH@C|+Y4J{O$PoY4?%$NM$i^ZnE&RcnIDE9yoz z$(VUk(~rFU@P&+kbc!H#6GK>}?9<)FUa?}LrSJo7ko?brL&d~b$|UiAbpwwp1I%$R zP40Zu6u(by;SKUmo`$_bh?LIi^-2UW1mf=1K7%}N8`S8N45@Mr0L_&C$VB` z3A5zCv(I!(k&V{M*PR5YWo6*{&Kw@nK}C?kQ4+zTiKOe&ITHL_p76BLwhoSmK)u&80*D(Xqx+dDw8FO)26aKjxU zERz>%F%*jL#q_>a;AlwroN^KMtYT^mxh@jTyi?lv_`qfUi+)g*{p4BXCfX~cWCg?a zXABA)bUy(!!o;wb>OHvh|FU174R<+xyVUy&+eZi$JIc6M>gZ@5e7EqMdkEOnL7pVu zd+lgMO$HT)vcCuZAEw?j9Pa*$`c0JRM2p_*j7|_edT%qMMvoGrMDLwoh~7mv!{|YD zLJ*7=okU60=)H?PzxzDrT>mq#y>MM)+xxrsTAx+fxB-!Q#%u@wTf?mXzBp`vH!XS6 zK$WYL|L?B=@3v6?99uVmpO(#KhAduJr=@RGyp{<|(w1X`>+0R82oL(Q@cl)!bhO1` zr5(?4QVQ-7j%LI(9)EIRU5jPTE|%mTp}V()Iy#jBEsxACt3+pX**g#xZyq2cYq z;_O?$Q-67ZSu>#vE->=Vh6q2<0rA_?ISN;KI159KaI-4`n=LR$K89-d09$P*ai-OS z;GmYf>-RXx`~V{<3AUT*g}RAWHqqk$tkE{}E!VyvuswYkL2S+s_-xl3HHlrKL3X+g4*`a4L zvp4`i+osRp%=nHQb6LK-!y8=Bp)WEN)NnIjJ3#F>BlC{J4CA%$^@zm>#mMBpHmJ@Q zpvtJd--gOp7!RwSOksE+W;!EhvP`nCuHVXb(#0q6b7fCugL=4YTp&~{33slUxOKJ) zv6csv=`}Yq$&P~ch0docwolsE{+gZr(2*65P_NQi3>$c+KPf6A&gDQWNJE|6_F2o@ zHdW_ew!!Y>0xuTI%F=}k6*wuM8^b_JOObXjf4jTn*QP+`thFy5L>apGI2gL56#8=p z&u@WS>n|PRL}7VYs8xv>H{}k*J#XL~^*E~JtrT?>1XFB}uIbhIA_Ws(jaFL$7=QhC z%u6JD)%!bPW1Iga>7o@*Ng3)4;F=e|*nP(yT_PKiZ+1{B&RW&V%5x0~8)OdxTTr|N z^>XKtW-U^16r>3igZcp8J?rs)96^PxuD0}myn-^ABk<(t zQJvSn#0*B+Ahked5Hze~LCJj{rUm*Hpd=uUW$NKA$UnvBzkme|I=My??a+~3~^ zd>YG+MUb}%@CX~H6m_UDtRH)Gmfdr=bDr#l8bSj)o$137NZH0;`qd$HPuR(|B5f880#R?e~VkrXud!j#n=vQz04L;2F=tC*Ag?o`+-y6fKPaK z#NwdwP$1NmoGJ5*7o)cR=meP^PYnGf^dSUU3~}`)6Af+9%nH8P*hudrZE8r1`?Fl3 z^XG8q`P8bWZegc*ps4IJ{J!E}x^JO7B@C3b z=%3RABWJRV8Af;r&O)*OGeW^-m@4}V6#4DCBuv_2Yy#`APK9MJPF!3wgeQFQJy2=u z)A46jdq!?65zN7UY4{fpnYkAL1i?Y8O=DNluzg!hW>61a)>CwvfHLD5pa2nxO~?ea zo7uDP0zv+mnKv)DU1_$Do~Nk+cvOo@TwLWh=3M7*WGwIZjfHCRRA)AM+(I9cKxrJ<&`6ny5I znj@#U_fLw;6zrt6#f9_x*UdOaa(idU;`*WF!U8Ip>AdUY&QJ3`x{HwZO-PI|oN!7( z(iw3$g|{7J3Zix-zwuKGD8UAHTOwFS4e`)r3PoB5WPQreIR#2)9%CZM)WFU6g7M-z z`uyo=hqYp9^*10Y-rwJD&CK*ozx-j@Pg3&SfJ~UarWOjoTbz14E!OwHP3JkfqPRvGH*<0`t0h zV4L9ug21^lx)+-CZZ!CjG)IiX4bR}7o6z~kz^iT%>qas#yt)Uku3Pz%STtK z%gOpXfvP@GFPhh@U!Q&HmVIW3&WgA8|NKrXXJ+0_AqnF;SP8oecpFNn4c$~9jQqU4 zzN-Cl_`mtI@U)dc(BS06pdy_B`QQs3fISn;07Puy8?+T1xWRLC6^7o}*>7TID;y<- zqb7*611eUpWp2z+00J{0HFW~oGc%Hjh5WPrmVn99fl|xA2WHtjIB&GOUTOx$fvROy zek%~y%rfOmKauCp0PslCXZL#DGL~lMUF~iDcMl)zQbYZqR@zMX?vUE-0J>rblLmIs zGd~?hWgI45V|vMBSbsrd>d`5!{}yMouspzt9$hq|(6-h_=3DxW-}oQSvlVDKqlMBN zQR`7<_oIEKL)ntZRJfIfJ%MQ^mgD136n!d1aUNoyyCT1yXluL5-{X^eLBGv>dy+y) zGf%e6`s1D$@i^o|)|p*MQ-T)|@5aZ+*I4g{pRy^Ok?vS(SaP)gW(F^0&dvDX4x=~S zOp`x#P%vJJmewg&NhLXr@OKy(M>^IXBRW{pvuWe3x3{8EHT(Ea5ka7>&X29{%zYI7 zbY0=X9uQLc$cmV$qJE^=h&(g7I1l-@}mGR*oYd-zX=f+v>F80^dZNEcg+2FD#IwuX4n|z<_zqK#0tz?Y6e8 zx3v67Vu)_KJRtaS;;_|y;k`VW;x+ssjqWN;WB5~Y z9(HrL*fUOaP1?h-N~Qz&RmR_7`qeejfyo<|>kKlm1ka0NY1KCQ8zrH4E7*>vf;j&g zwnkD$POL`?pcfTRhp&{!esM0xIz_FlxSPzd$WIryROf2`xY};u+<-`O7r}4kB(63# zuy#T8d9a4J5bnR`m|x!P9~_vR@Z>%IRB?@;D3|;AAlb|I@}(G|a80naHEGHbxgu_# zsv7faAnxZ4X{24i0f5vz(JL!mdGzfu=Csja-EHS90m-#>NcpSotl7ZTbbz zZ3p$P`Oz(%+y9#8aN@sfQs@5yEZ&Ow`BexleE9>UhfFT3p((rjty+3^<}gF$_%_ zS5gs0d!uUOcIK^1%!?GEomu~m$(#RHCt;m!iauA!!6$I%ZxyYXF3C`Fb$K*9?=*UzSx5L@Y{DEuW zG4KzCdiMAXLjcXL5u76o1_@~hm+yC1n8r9Vnc z_0Ra)hK#=W;N33S;H{P^$;)Q$HlZ-i6VNvG2fr=916PXYs3P_wocEkdwxm2sn9lX7 zD~)T(FJ)xLDG}APFVZFGdP<#`^`!Pv>41FcD5S_rb?(T^G+}7#3K`pCBtDYa_Yse* zM}*Q!>(c&Tpl7ALrbq--sQtX@%D;*8@Eg2{A-vQDF2@`CV zE3+l^nEUF;0<-H`-Z#0t**qByZ$JGCaxj1 zq2b_QcJ}j)|9#YB{{ul+m;6~6AZe4kNI=1c0lD`aaJC;EEa&V#gzWosSOLdI(lAs*5{U=OX8*?QwR?y) z>Jx4oOb_*;hUi-Xux1@W%nSnW#nQCK#`r2g#0D>0@$fI7Lit7`ste#8Gr-B20n5mK zHSmfb2il9w76*JOpCS9dIy&2BJ6d@WS*js0M!pO(#5n8k`{$aXKth8Fmku;JJ?k)E z(8^H6J}HqTk(%93PO(uwPQPg~Wg|o;^KcQ%HYqr0NO@KHohy6c$R_PxQ^PJX=~$f2 zG&z?WuaiUY3fQAW>?xjdXpBO+HznQBN7rG+@mXffwr5yIbd#+yPbsveEMHkVV0SKQ zmQD^)=*=7xI&G-A73#ixPhF|yF<@)2GiOZ0>7epHVJY1#g$$)rcpjdkWbf0PH4lZ| zG2?O|lsWE8{%!?pWua%aIsWNKi9wT;C}y+Vi&^Vvhk6p1-!MAc6)0I1hDe8fG(>d# zX(TM9e|~~=&Wy*qdkJ~9n6@?->#+MwE{}=?s8WsgUrjsl4(W0{CIDDan{%zfvqVGH z{!q6F?ugy)_?o*N$}m;_67sm(mNJ61(NdDw>FoOvI04St^-_hyhr+aI=^$fO&Gbtt zTh-saeV=7mZ5bGZ+!+0+jm>6rOWsDLi(WKT67Dz4pj8LKE$--?2O!k2$evBF+{t!^A(}#<$S-Cy-1OO=nqxeQy<@(0|(-oBN@on}_} z_5qewDm?y4Na4o{?@i&$jPD7NW;%f6S-+Qh(;cnV3#(9E+jW_RJHF2aBB~(X8#PERQ&8L0OOYh!Ia1&(+Lx z9<#U_V5zJ6y;qWu!$4qx;Wdhxi$Ou;8}|T=^Y=ILv|<)DgUz>iFJ{d{kN&6lmg_x< zM9t(!qNHy+VZ%n)fX5!_lS_kHJu_J}*=S5;x6Whe6C~@+{ey4xhNmvca4*H(N8{nE z=l_XhK5q_(5J2hzZANmj$I{crBk#=|!2t!F5vzhR0o7rv8yXMXUmuZ4BQlmXk z@l{53tDR#NFn?47%J=s^;CYfhlUAG2ZaD4IwE+)8o!8Q&9PSvs^{}+zWzr(M^t6?o zVM*U)%+Gi;_JqdQXD0C4C@7&hhH$Ih8FJ~cvLL5l4+P#WSlO(39#1|~4Yz#iCIu6* zEUum~dwt~qm-fVGQsrxdDlxQ65}YzJ_TC+c(t?YA^q8rbkdHB)3OSat`#0aNj?31*#ryo@WTMJ$cVL_3F z6dH)8Q(2K{K{&iv7c&RJugV`K1KNy}`!4ks|CZw6v&KD4!2;WA){?P1r1(c&Rrcf< z5c1m4aX7-H^6&_E&V$LOFupo~;T5(TnkepZhk~&Iktqp2WqIV===3UG&DM4)t2+oO zae_Ii^Px?}B{<23LNeI;_tDB+(%lx|_eZS3BYa^vEX3Sq!Q(8$n;I!gP{Im(qFa6k;!2#2%G)#}!I${3^kr zqkotEb|`)Wi*GZa+hXHWjAihErJfD;4G)eW<3h-GXlND*{js00ZQrTU_$UH;bDf5+ z=tla)Pa3CN4S$NS`|SL3(eU=gCil&(k%w`5xjIux=imlnC#F&N@=*d#IWat3pWuf} z`GwEf+1ZjrvV9}u-Dtzopi09F-w@k+w@+nW?E9!mKN}k|yQ1dYpzqi1U;M16c)RCF zgsp#K25P6AU>{J)0b_gJ$NJ&BDk@2Hu+(VzW2?&t~N%)%E$AjlZW)Xp~) zDi|IiFeNCCeX-1~Uqi(vF$(4hu~0F5l1+dFM+mZLcYt4u!c ze@Flq?5?j=*Uf9ta0@`mE#;yN8eVkLMulm7$yvHETK%673QFhu2q~Kp^e{5<2uj%o z(~uQVDip_rj!{4@?Ey|NaCOwS(g-~rPn|fT>V;uxAvVs~{}Yhf^uX?b#0Hy*JF@Iu zaUM&~EFi|A*xm}?WnAz?d+e!}!4$$U)6fuD~$K#7no8Go8g+pf5m2qUi7O0_by*GnLJ z^v}H)nR;7k^*x;mW!6>*2|}m+I00*@1YI%mb5KEc(vAqK?v&B-FXDdV@s3%!)U>K2 zYtwq7kMY9kuhK9WDdX%bdUt`P01Ek&`=!>b)xZ$8lb$D?U%JbV&=>mdjq2)~;k#Xe z=akj&a^`StQ6FsMJkOT8=MU|I<^Awwf~nmpUlo5AH5}>kLmXtrZ+^|9N@9^q@vI!@ zmHF9RL$0u*Q;+gfNy(+mG4<*r)pC~}QsFL&t+d5z!&gwQrEK77@6ia~{=M@$)qoN0 zB4k+E+Jz&H@Y|k9mevnAH|pW>0JlAVM1ezM=kbU2ed_C1^m`#6PO6Lr{Ro>hL(k|S zAZ17hMMC5n6MS3GVc<186ZP5D<}W~e<+j0n<4_NB#o^2rDy(F()=o=HGqoyjU>(7+ z1U{lw!aa9usn3F0`$1$6(}8sTadjaiGkHoDFa!C)Qbk{>1&MbtJ!aJr{XD10>_6DA z5cH*mtey$_|5%FfgBb)ALbAK_dw$2n4kaT+1p;CI{EzdiHDOo)Mc9W*DFgP78~) z96WX&+jedEcJ9-RsQW=}u}f7OBFZO7*WT@POY zg&DiS)w;muGE2lf$(@r7#gJtf2x+uK;-s~g8V>{x{r}#D>K~X$kgmTW|8NB_Mwp0^ z%voR_7Mp}Fk zWxv=}$rLvmLN-vGd$39>BGBR6ZXm;mnz>sr?$KP=*DT z=C>4%=~F2=q#F>j+jPqJQh*Xlmb2)1Udw^4`22IV{&qvIS^K87VZ-Uv6d9kO=bI@T zr`xX)7gxi=Nt$*FWgNd=zqX}S!(}QNNnp|M$7j$YpGsR+F$yy)@}s6REPwL$$SYC3 zLP2LBDzliSs;89g>GSwrw$k$_4SE*i+qs0^#q~}@cZc!_Gfw$Yn|_Wc9T|fxOZlf6 zb#W=G(Kz12H4gb1YM0;jE+jg5a1p{chB`eO$KXS8RjuAve#qfIVF^QMrU89hY}Lds zU8JM%_4=c7N>2|;xa}mQMj4&Hjw1HkV`Y*uGRUZ1IZW9xAJFKg4j=cUGN3S=wIn^) zXHikL#tArCqx2fcy18a`gx9misA=WHr&DAy$SYsu125ME^R*A#laNl7nh6Ps6@M!{ zo0CJ2g1L8;s%cmA5zjZp=!!TTQFzgY7ybE$+hZ+2>|dW@es#6@`}^Y=s^dqHTm;Qd zn3a3Y>c2x@K-^+I(zyOgxgb{tTl$T^f-ZAzY8LlO`}uD)jz7KhAnh|jZe&TShL7y& zB!95Z-FGMr(@n^JIxx2(XIIN3s!V1idvvAMo0LuL1fB+T_+0Mn>F5^Taevvw`?joV z`>b&>vgSnl^mvkO&*5IjLew1U3Z0(ZF*6K$KBj`_S8YVS=WgN!QFyjSD6)9_=zi_%$D{4RPX1l&t4qE-bDiO| zbX7K8rM~|5z=b-nl=6O=@kTj?)1#00TYIu(V4wTp93Z8r^?%kTuW!1fT8Q7qyD{8I zS;(-_GcA3Z8&{OzRh&l0{b)M|&OBny>?cgBQ(}Szs+uI8|PK_Kxe5>8rJSBj-z0%2tMx?6- z*K^9U7rv^16~|3<21?{XLJMtbTlByA9vI4wq}mXze$FpF**Y8=X@YFSAVBzKN_ya< ziPvM~JnK>_U6U!(?BuF#aTCcD|L|thLcHfyjuh@Jb}#H154-99nz<-XdH2_Q(Q;#G z$!|A}zOnlJtH$Ym1_NEG_ez$FM{sxvWbXZ(Jk#MW zx5eP(AzLOSBL1)*Ar!@R)}Eb{cx>vNxjj05u3sQHonvyK@xGM|cNdM`!_;q^K^K@F z66~F}x+w*9O#TAp@FzFL}{r z+0QwAZ;75TB}fyt#a_odYcj@t6u=SbPHa%$yg@f6D{hI0-l&N6#Zw7vp1q6_uqIup z>VoMw`4_H(Zez1Z)4BfHW))V?#WivJ-)z87)wBNoOtoKSvBC#~elZ_TZ23nRgmL3B zY!`6Js_tiPR3)2Ib&&~;G+(_CAav^cPJ8_4RgYo_U2^<}7DP{$O=(yAx6mji&lqG- zdA>NH!YEZ*tKchpfR0@Zs8H)btN$lN3~{#oSj=x~r#f{qg%rPnT2n_GR9d@LZ#OqT zFWU4jR89eDJBevh4;ssp#AuUDbowIGU+*@l8N1)B&E3jY|UL zOftN~@$gHV-PlQVX3N|IE zAQJUp!(n-TvS|fq)!Bec*bboZww??M;sIR-<=X`bo{*{^Fw#HUgltpIb7pD$=d1u{ zmn@)qkf~1>+KU>aSL)4kb`;v~4Bk2LH z`~?#9Gq>?r;%V)CAuIS$EPY%-N3t{rH6k%#nPEcEVSo(Y*Eju1Q_0R;yW&6*+NxfI zp#}I3FM?K}h?=1LoILM9(~mLfBsn|Wd8THk@Gd)wYt%*L^at-z;fit_!4YA-#?!+3!T2Im056l67VtVJL`OmuzTYV36a!2l^}6N`vq$NHd{C%QK)cx zA_&4Vdfl1O`PM&Pcs?%-W`$)uy3ahMWe*dk`GJdW3urV0R>w*bAMwa7yG@PkymGS# zm0n8!=B<_a1z~9$I#JU@n(a{7@{SYs>a~+lk&1GNwPDu&RGef`q)e?AMrBwuipTYL z(k7E0nwz`0xL|1`U=_F|6VL)ys@#ir;bE;I(pzfpz{=`ph2iBtg8G*?QyUL$#w=rt zBwa~#%FTIN$(dd~P+;U{P*{eK_$_D2X7f^1mg_-)5H8!gNRw6zoCJd zkQId+``0NpZ@4o)8dax`;LZ}BXXFiJNyqoK_^8uI5-$IV^);BkKgUOKM)6mc<$K%g zbS)Hx!K+iX?)!#g>X0ibz?tOrW-(10oTvE!GP36Sb>=YfCMZqUvH%ZxWZgr5(+MRg zLv6(t+N|V%Og`H@01HH|jGt|LuuV@-S5;MIawpa!?G`gwF!D3oRZ8W1$ujNQv{PLU z6NfZ2p5F3gz)6?QXnIdqSzkhkuROkIQK_$Bc9vB02@r{=I5U0g9BIrP9Cpx{W)-Qk zJ$jDoAOezP{EcBVMa9Yx?`1xh+Eumr7`hKq zOa$d_CiZ2~^IuTq{KYhR)!bPvB5VD(#y-|ia3NZ^IwVa$x~7}s$!$618xYw- zRQtcYq-b{stKEOYDk6dzNfS6w<$?6*LM~o!O^#J6paGf=8(~3lv)id2L!&p&>@$LN z3v6Y(F|vWQSb$Iest3k#1GwsGfNKT#`~(O}A`K*Nqj)_5JOh&!fS2Rx8VPnRY=MkC*H z=u54KDM$PcavZ|n-U!-TmbzS#d9P$5-qLZ8TTOg!v=#YO>L6EYBDK`#dut3FQBy&< z{dKyNVmv-y@Vt%u`1_CCcg+elF0Vp^gCixj-yORM8)?|T`;pJ(NuQHneCy<)5kE3n zTYC)mgF~>kPFYuMJgvqv-;!c0Eyc`SDv5=YarUba zWe?cfDwSK@J1GBC+Ce393bG{IKP9g1JpH>lUJ zmGbi#Y+z*0g`6GD<=h>{Gnk#rivM1Tg60EZJc$q)OZz6m1H%Gq%KPLa#l(MwU02SD zY#o`O*Oywk)(Tp;yHsh}QWTvCCD^5L-SD2S1Rlw}46|4H_iwtxaBF3;s!|?KtFHI~ zCKVt!w!7=GY~FDR&1qXJH<>a4C8#0g)XRsEe~#k&K@A`Tsxb}=~UFdPPjez%2uB*VRXHolI}cnqkA~+c;Ts3I7}H^~~$?oQN+4r}YjBLnX1O zrjlSaBEc&YaaVI$k!>bhY2}FRCllKf2S43bK^}Krm&bJ_|D+GJ-jth>{J_X-;No>t zt+(e|bB9rDtwJ7{l_nYXBvwAHej*Q)GOHcR#r6kO(Tj}DPhYiq3(V0lpniW-<)4iS zXn6Xl!+K)9od2EFR{DTc^`7;O90Y`H_&Mq2$bW9-=?R2gsuy{eg*?5op|`E6Uf2@y zz#lL;@Y)a+=sE7_c=zq-psMZu{d@I_qGH+#FQ`G4>1?Ip=gPl%E&s0h!chNSsb$}O zDdw~^SC^%s-L30A!hw?DA{n3cz*uhXb+58E&YsSuCg~1uV?aLu^R8hSC?QmX;|6XB z6!&Rf(qBe zp5n$8*3bG&s~_9$$1ryGo7kdX@NwLoQt3>r4K%4?Wp{t-+E13_pujPL_&QRpvGJ+V zZT{5RSy4KMg7p?>?H~uZb9#bmn@jSBVpCymq(I{Zk?JwX?ev@VU zuCZ7#n9sJp{yh5~{)LV#wi6hsuTPzf?n&HD6utyqGjKPnY5nKJ5SyEG|(^gcMp zY6w|(h=lXdT-l!RoYdj!24JS$B)e+RjdHBM)tT{nj9~PC6kZHFq;+(IFlXUA396#k6&DGoW?(@WX}&s@vNd?G>DHv7phrWj>*z!`(L%+ur}}V zV@;MzzAv%(jQR5?0f$q|jO&z{L^Z+Zh0YL5pBvF_PEiWQl5=(hrQH*RWbkuLG6Nyd zGACSn=RhpK?aw5Xvy>)}netWjAeSkElgv(=LR07EMf?g2uz|2#B(SvCLCk=>;Wkjh z*X7mmcrY!?mK+zh18NP)H#keg`3Ja@&&03g-!yaogys#(z9?Y2{#ib`5OVFaQm;Fh zNYb*p)l%xfl*zZG1J$&!_llleO@LUMd66&(Q4xCSRAgpl(J0uB#JJT~5zXkMEL|tC zsFjrFu9Bu}D%=nSCH30=7ni4)j6`dop7xl}uv*pT>?4lKz+73IJO0J137_d^TNYBr zR^oExezmxmEI%dp1wtq&Y1*^)P7nqGp(gALhQzU@7fE(rHE+z$8k|$24mg=44*lze znS>`$nh)j0jX6*{pHf|q@3`EPGs`R3sP$gqg8s$|rf9Y)A% z3jtP-MjOD$(an>waaUZFefuaIoU!p1U?=Xc1Dn!bSnpu@##wiOAm#3fGSjN&FaoI6 zfFS5}+9RkA!hYLfn>w)DEM8{SYTq9Sx1dK4W=$h>5_QJ;Yh7IrS6cOeENf-Ki*{ly zA){R`C&a@?3g}S?S}%T$TOZ_i?s|fijQ$%?2D$ub1#g3R9V~Z-xa27YQ!sISDbOr1 zd+_RQ4-D797Q;Tb4IQY1=zr-!zInCaP$^-R9^qp0G)N>8MB=AG4l4R#;Df_Nq3ZvL z!d1O*w4uGJX`iO0s;ZiVA4rg{Y$YVb+P8b3$y?Wo3#S2Cd=`yym}Jj18$L}e(esAv z?HxY6vT)yHdZOB_Vkp?MLl7T-Ibdvdu4F@N{f&$BPeJ5wH~XL^wsMQLL+Lk9^=FgO zqbH0nq8}$5Ab8>TPEX;SS!N#+i3y3xK)=%jkCi7=i{d3mQriC^Qmxo?OlG-8P$h( z;J{(S^QRUHZ<|G%onAH6eAU7JwGcnbXsJ;89v;3?HRNT(nURmCww=eLU7T4e(@g`5 zN^rZlef)w=lxP09Ld<3+WAgFv@`R*#sNVJ^cc|56A>Rj_!S2XrA`8<91-&p(%SG>^ zDur?u6LystIr-f+7A4ci--KnSr4QyUX>{@0gzGTJc&jZ+Y|~B$>%SvN03qyS<7ix# z&&0$e;tVH^U76pX@gNnSl=mAWnt}GqBr-g^cwOA1?d8L`+r9tk;H(>>D^+IeYwbQP ziS?5^x7S^LUCu+6h1dQY#Yn87|Nq))U`wc@Uh-mI$saz)1k zY?)SfX{Qik^DWI{%_7-9aIz&6a<;i*xDMA}3(4xC3J(uQq^U9*c8)@BL6X-if6qPP zAJEoY&kvXFYSIZxdXN}p0crKKKa~*tbzO%mv!Bl@Hhy&2x2MZZSnZPGZ8MU26ABbW zeD`$e{y|H9=_K5wHqH|+@4G)b=}=hz z+xR~F11lo5O_4tE$CR@flKLGdUb&6W;)o%*XWnu?l@OH1I$6d&nbNBbFG~FA4ucEn z9u3G1l{%rT5-iT8GfU!KKX*TW7@aGyQZAFKV}H3jzNjG+8*CqMDB3oQt0m0oHm~De zP~i>_0Hca2-1wiXJ|?SiDX~Bx+*#alG;@XIxfqL54dF3WB5bJCZwao#wFb6v9Y{NT zb&#n>;Jo2HYr~naOWT|UJT2g1N#{q04z$;Hy6c;zV(<)S=QKv#cvN`7D)fy{zLcf$xbggz0l5F#we0v5lC zmohTR(Mnx=jp~azOW7ZlJH=xqJ*b9Z+cl>6A=A7iHTdv2cPTez`W2 z)4zSbAn<6Ogh3j!e@P-w?zWnXIsG#uxEBTEyG#zopKbfN!C_}k*x9Eiu=m5zaK8GV z@w>({5%4n__OONrEXwDG+uKys6S9eCH~UNXQ>nU^=L%7tVhlOq-J8!X*PoB*SQphz zNa4ENZg+!g|L?$SP~%jH_#0rgEBDX0jdK;JV#e|j^xxlACT!>z0Ujhg0%fD!9bvOu zkQ$U^kP4tT0#hfZ4-U6Q2VkGrnSguBYj8M74@CvA0fh5r!ci;T!r8Q)R9XOS6$@#` zFKU7T)yk?IMi?4q8OZ9YB$PS>Vy72IDGyE;ZvB1G-OUhXszd9I2**LllpVmH$N;V?Mx zHL*lt6wK<$WtU?*y|4K*jXVF$cp|1-88S41g0_zK&nf^U`Zr9CQ7_@#%Ht8;ziCRY zKGOyzZ=Va6K50A2-z#18LClH*qQ4+uihG9Ie>CAQZG3#@#F7MtXV^lSv?C7Z73XfL zV`)yPu1IkYDO+kX!Ia7AW^OXd5^2e?5cF$VgO6V}OrWE1 zeVGNV3y^w>eER77n$GgKXl&|Liz8+ZOx;_4rQHg(Q#R=y8c1DA9YHn5JyEt{#H4heo zDoi`Pw>E-@9f^@;P-!pWE0F#!4KA7E6x0i6j^ulY;y-q( zJ2Qqcj$%JQDC~3>Or97nEv?(Pm5>r|iLLP8d+&7FJ&GhYSy<1$`NJ3p#7GJ}haG3Q zxxK1u>P~zraPB^%eZ!Z5;COXSLAHGGs6z=%b8ZokGoM4_6hM`gxlQ$~JjLS0F0GLO zJpA4>D+0>5n1)U^bgumWrr^+t%U3{9aLpyi3OvKE;eo0HQn-Pk_qCSnzem}(R_d}G zg>s?KD4|$T?SYLmVEk2=g`kqKw4wuoirFoXPlBSc7T8Q&dF;2z0B*~~3I1Bk)vX@j1$&v4?PI|t7@ZoVmY%8sWQ zV5Dk5sy;r?V02^9U937jT()pv%ut4k&)22ZOk4ocya9Nil^zup7POp3e8+!mE=FP) zd7q+a<0&I++c(v}9f2@EMSK|JdxL-+bW%Df)mqp}w#%;zaqro6-u1hI5|82S86?+KZ=T^NNzyJ5w}CCTIXnQAI{2`>X`d%r5duT>av-; z>%Y*V`j-jHw@y9ac&vRsvFy{kyXK&wPXYQ83?@7Rf%09{a>`tZ76!)cY`l_|4S%_2 zw=gSNiO8bK2zLm-m(J|YO7#o7)YK%}z)jR6lz{{1yOctJEd80xPgHD{a;>!^!ib+W zSFJtDj+&ivI;Z5Bnk2VNImYlnb!_ES|Nc17ftBit*g&M_n=(C4shZDG3CKB{csS_b zq6>^_%`=yXH22dJy@vD{S?IX&zxd;d8Xqr^mTS@51$k6ftiwOnVA9dVpMx;+S@boC zf(qiMMQkd}+9uq|k%9xUjY0|rNR}fY1QDy+&=l@neXvo87 zlx{Te?!x$~;2P36M~9EUtcm-uS}Z{n|A5M2`=e-*#A)O7>1o5?>5#)q_tp)<01)8Fd@f-?bxhlY+?fH zI4nY`tHe9~Jvud_d4=o`xp*T1Mqtm(wIG@F?l9xlTAb(~qjYm+Oy+PpyzIWNa@~W| zp6*HF!p6@g4&VH~+U85?xg6h5>Mu0qV|PV#ERIWFLVJcIzg)T6zqqh_=i;FFDxHB| z>ZY!-VMR8Xf|0O5Qc_mse5NgRDk)heV~XPUsp4SFR^bsREB-Q}?3enN@I z^`6|eyzjkgP&TF%dfaAkg+ zr+VQF?qdBYPlGy@@bfE-!oZ`xCCpwFBT^a{r~7M5wWAC;cI?VWjG9~W{F?*lowvrC z;u$S8-rX@J$`$ONqdDq3S9COx3Mzy6ev@CnmdIpgnmyRMMGxDMC`va}H%V#~P)lec zo*Dg#bsih>`Dq1Y5Ji?PSqRC9j|g6_z>4$QO;{L>vE< z`o}>6E<@?4K(s$J-(Fk=z6{V&Dn4P~lz+e!Kn9sTI^SAza)_wt-mz zyc>_(K#@7#!hWBz9AV~+Nki4~?40+j;o56-6)PyUrn-ATudj7l#GOi{?E(cgF1e9P9Jx&bJkuago^z_GdiL3e?T+pK#9GdN$S!1-vyqI~b0{ zA*mK=UT(gEh(}r!|A=r7-mEwY ze%vcOgGn};Gvt2KXhyG;$+R|r%U=p=E^i*`YP0Qo$~K-tlkvQ8<{dHdWlwmlr6QM! zp`0rbuo)I{k|Q-_?m{(SzRuSZ@Q!+X$_^9d^$tqiy($)$Rz8tkL%pt3%hL#9-Vj`d zsGC3t;v0KHZJ`N$HU({}s=bjfBJ_NhlmZ>II2glUNNqc#r*TzHR9}BTNq6Y<#Jdy< zK770WUm^ZKYobe@me2q}@4}=bst8owAtsdM@G(HxlY3y!K8;01WRMJRPmpIjCEHZ) z$PU0>;c0cXGHC&q(Ci?Kvy<6KlyQ>V`RpInUfAV{1i-(V=mj35>6)`P6N>HW_feTEF);ly;>b$-sk(md?L z3^840F4pKA5*c2eYY8vetZ0Z)d8C{J4QR-4qHc2q``<3@*Z*lrH`=e6(KsmDB8_xt zkv0j2S~^dr-Cj9|lGL9DU{78C1AR08#mAnx54o=N= z=m@j;&Bw6mcWkKqo=Y8~sEA1(Bl(M|EJp{zQ8_LdPx(j=h#e+u0*`}+3=2b*8;aSv zUkO}A^Go+u4Iyn;*ZTv+C>N>7o3Kh3{v1tfh(-PMh?;8&i4+^p@bxZt#1^ z4vLG=qPBMwLP5JDd@T8o{XL(_139RUg){#l?Y%TvXt>18Y z_w(PZtTc~A%E1-o+~XnV+8PNh@p0#E;-ZV03oW@1QfQ60n@XO)pZv7f^;p-%BbE(x z3Y<*pQkjL>m)+ewl^QxL_!rjxctffvY=3Vr=DkyZyW?;`lKH$|+m{ItrNX4{0v~c~ z6#Zc2neOKD>fhHlN~SkMNTmB#-6xQ*|J^2h9i?x9@M9pNVD#cywK@o}k4<{~t2(Qb zL0I;rO(3c2|29E`svmWWA$)=tg`v8F7yp9svv1cd24?0FVJKiJd$U!irzMkO0}eyc z3sUyLkdP}Lq~vZdZ2qs+Zr@{QvSx7qVAk%5wkp$V$zTDSl~c|IFy8R_qsuc3I?Zfft4t4o(~Z3Hif8RaV~1~88q{syB2E!9d-cjk{z zQZ(9vbvf!;LecV&hl<&K%mPU{-AkFWTqYK)K6N0K81;8RF3EANvFaj!x$6Mt<(8JR z&QtaF-GR&OS75L=Yr|5fJcm&TPxiJXa)TAvd2K&HsxmTWGcrV%!Ys;}zFQ(3uA$lH}LU2nd?}53R#>tZZyN#2g8q*$XN}xx5?xM#e~&Xq|gkymYXM zW~Ect($eANVt(%@W?Dj}H77{7@|61g>lL6CexmxCUBA^_R?9B~eqPM66eX1YBmpck z|9`mp%b+&ct_>6|?ohlGD^74)pjdEs2o!gBcP&nE2-4yf2vFRuxE6PJC|=y#o#)Kn z^L}%FF-(U1VCJ5+)}@ph0f6ut2DPQ`Y1XgriYi+6-)|_OOU0{cQanbp{nID(_xDq5 z>5Gw-q0pPd+D=T8CBncvNskrr3U=Y?)!?BD>ZZatH5mB##)D;(Bu%P%g zlf>@F^bOyBq2-$sx3#TnmFCsF83IHAX!4aRkRymxh`BX|(eLYEx!Iey~grxnEm1XVG9EOkV%-G_qM0o@B5V3}tvTc>qS znR2t_nfT_1Ny66n_>!v}Y%ju;`O5~!`m~RgBTr5z^FKZ}GcA~}y4LTi!wqNS^W5DrjvY2tCqj5Ey!r;7p@V?)cLHie7TM*kfU zaek2wP_w~vXM5T;xc^+@xqMmtQpw2*d#X3jxU&=5O=7wx9miYQn2+6woKySyf_*QM z2ClXd!XR!nZvThce#$2F@#C@9i||swKzj<#g`JyWmyX|V(vGQD#$63rrRq%(ntaT4 z^!Mhd`XLzL0wq7C*EV>`Sr!|w-X?!>M(iuL+@hNDyk!MaAYczK+11DCU)@;NWMG8B z|8LR!Z@vXJ-oaD8|5eY4peO|rr%wKJq0Ur50O@k4DO@pdp|sAyt2g3l%*%Bd9^Y|k zv5hQ>vr^v>@wRFziQJc2gu=cGa`C>5z%RcQBxp(^o=G`lhMvAImPpt7JAWf2_(RN5 z1|TcNd7U?GSzsGOdZ-ry$8Z=kjgGQZOqs1hR- z8dFZ8F1s>rl)k*EjFAP>aPlh){|E$(Y0EH{Rv`SQRjlz{yqA6Xl~!z)#*W=@8C=8e z=r}BQG3ENf>us|wmglQNbY#1#4F0wf?8P{)jb&PZ^6Pg{-ETXHn!+aX_D2!h3PmhngwVmP4SH3XMJhslEa=L{fJ#7Ut zt+~L)eUpG^d*@Oa#a68q6aNWI%-=dcv5&3@DP^DzwLY8hNTAca8P!oFd;40zLg3H? z+jk;{1dYOWhd7pBQNOP!Nb!hDDt$x{s>}Bkq^Smqdi26s@P6ehI=C3^712ZM!n*15 zuT5bb)}&Xf#%hQW?vy__y=dQ|<`zQd{w^n=`!O{*#*kbuZtcHlAf|10WPZyr)X~wg z3JItyt0vSs>rOvUvZIbZet7q~i;tqY%KWiCT8Q$~2EsNjI{3yCt>mQ0p~9$j$ldMz zfEi8om5~+OCdH*%Wf#I=L4{tP=i9tz+SdOMSSf!MJj=uRuQ%frkqeHTAZ9)lVne$) z=J#S59zSN5D~kN%&(x6bLWgE@!w;_(BhJT%70GVMf3kq=?L#FIP5?C204xH(|HMjC z601?6B3rw$Zm>q2`%9WT;W4;6&#hZCMRC1Tox4k~O;b!`vD*1j&ID7V?6Z=P_JKh8 zRp&VNXx__Bs{iYsJ$55c`80`XcMiDRyb9kr*FtkRtt~w8fv$5!4^2{fWpN^g8ckzvN44}=)Yfm49M3wiThUg z5xj|yrDITWLA76wQ}y~8!#5}t3Q?_cA+AH;`{utwkTi{6(XblQYn2*4 z&{fCY+WUTx*RiA2`8u)Sy->W*&5b2-Djfj07*%A zn_NgOEqB)mS1;{u*NniyZY1Jx3N<3np-(eexmspcw-?_>>V}B?qznHKIx@pbsyQSY zWR~v-v_EFn!!5EYmnu6p25XiQt!|{H{%U+Zb2+o6QyeYZo5h;mH&b(z-Zj!xwN(L< zHW3tkurNtT`eI0{cv&W6Qie3I&T}HY)=zv{lt=)5S}?L6kJW>vJh7&5oS6U%W+ZMJ zr&C&=Q)pt8W7>v4Yd={N$&Q#okB9*4V>vuw{hBL)alizftEMDWacyfwQ6MFUr}B#f z{x5b$CwWuL>Z{bc-Kh{MSB>{4_LPJ9^2){MnG`V&LkD}pm}Yg1p~Z3DClCfLGon`Z z+4MUUrC_2juAT;6Vwes&*b$P^>jSrSU&>k5?g_5)rX{XN+6pFk#VBu zYHf^K0}oPCX=?hshWtnt;dRNno!1_CxVm!s%j}cC;lQKsPvX#L#^0IgIww;V{fMfR z6ciMc0-1uL9-~Mz_jiEbmaaG_-UgwTlq7!K)!10J**P<=M%4T9cqf^1C4)muTMtz5 zzd63Hs|nmw4|<)=D!&apKiT^~2V27?Rc3kfXpoXdvx+k0)+z3ZEB9Um?N1vP+%VHJ=_D?v>t0rBoK)ydL zZy=H^BwO{0-Ze!;c$UFA05}#lv24A^4E9Vo1-y92Vra2*EVGJC#+5#YDx1>SHy~6k zi!w2l4tDf!td(QcesK_x(whDBsjsHZLJ=~S{XyfZM+A-6W7#LA)moOdehU zkK@~x>4Nw#7RTD?4LA2m=0Zoow&{S(ZOM*L7?GO1f2w(~-LmX2r33%Y2B$J0zm$s*WOQE4;2o0LgYr{a`2b}Ha9WxJfPVW{HXCnOaEYoe9%j2cP= zPxtG*b$!%65YNR(yML1?q0I#El^apddsdIL*Tc|V+Q5w{fP4ae0y!G59g>9y71S?h z1>bYM;-jGqi}kUZEDB?KlE*EXap@ElD}Y_SYpH?n!&FQ%T3S*X3=G6%(dcPzi*$mq z>3wBKDFfB?5pZ95g2{2*P(cw#yn^N@L|`q5GU^?135(}t9<8Dq;%IbfIQ#%?0B1ha zKYUn$HcORht>oHZv%SvdUXS&;%aI;0&!;RUvkp+OoK-51=+RB;7W#op+-{|MX}X>) zoh(2+m&+BoJP|7EQ2ozrhr1xi9UX5S?pk_()n>X(o%zXayN1qyB>#m&g^!v8)(F&L zdyaj%LUeD3QC0HeyXCpvU-`ecVoUG@fWA*QzZJh7CX}AO52IxUS94wBbx@enwlSyI z!%WDrBSNX8lvqT^YS9m{hQ+@*4V3}ET+;O|K9&&P0qbC>x#UP$;EkCtkS`R}c`irr z1`1k1{1ZR8uxGkaAa_Ny>MU{ZKhcz1{4x z%N+Zg2J@L9|5Dbu_#cXu#Z=@y;;i!jmjygC?s{G5)(q@|fA>FDp~tRa_T!SjE_j)K z58MNDz>z~yVc1s~H3n4p@kJK^w^EhE(4pt>>Kf+%=Gg@rA~f+c=ETs&Ab>LE+{h7Z^v=-0$RBZ@m!NFz(t8^W+Xd})<$g3_ zsReLm2byGTRzjPC@ zZ!t$%H4w=MBy^`SndbntU?uChd1k9}a-XP4MZM}O3ciVb^KGizwKq00eqyIGVskMO z&mL-6n{+cjPE%qBYs>Zk2&pM|jNnRSjlyhs#`fqh{3Z})ImX5ZBNW!hzcUhY@591$ z^|hyRJJEf25jhixt`1_9J&|`UVtzqvl#1o2dr7iFlmfFg?bTKw6z&Wq%du_muK5`x zT2n3(?YF^FnmddGjVJZ9L}zZwdg%j(E0N4OGryAm40uYrFj*1P&BDZIL;+AZGkhkk z$?d8TW9(WIFM!@@Q5pL$j$h)mVsAM0p}aP;jze$$J7JQX_#=wB|J_ULZE~C@!8eTP z1H6)F$r&}686^$2c>9603H27)%iVULtTE{_QNO0s zz5nnM?5#tZz|#F%5s^(|RIt|@<&MC&DrrdNM^kBURaM95V@(kLZJo9k69u9bPae%Q zP&4nA3**|YIEU@&)5M-`>MZpM@~0oyK#`wi&tl!0sGwbtnvy`~_q=aKiHUA7t%nCbxDD~{@~Z;F zz})50ggQri9L6#qhu`3GMR z0|9|w*Civ0q#aWiyWFaG>qy2J zT4MnPtqf1ytxBo$d~8o&U&AQzLe{NoP}c&Cl79dB^P8(gpMuNY!@?H-~> zn3@X5PX-~KBE0Za;tU!v#lX4nCal`I+mHYV45Yb<>8Y0zuPu6$)g6=DPiwu;IcPbpQQ8lhx?OtKqG@bV-`5Rn6*m660_)EEluVve~E~FC-+e4i8X_n z`Q)nGU{`nk&L~Ea4YXcH98&41i3#^8SSYd`E++W-HgTMII9ib$Jg;8_$*x0wln|rKN1v;aJCy$fu1IG*!(8P_k7Z@Qnn2*MjArT$zLtlW&apheu zG)E+XJ{GzPUzl32c9Bwx5)u`jfl9U+iA9Ffxl8``JA%c?JRdmX8i{Mi&NzEB#&gwh zD&B~pyk5S@d}rGDJxP=A7Gk9>u%w@b>wo*_;i1Ko=eGyRG-vDO+C?*)#%z0B)npZ8 z)3R+H>BiccgmfbDyZMaDRd_=I6*>8Rx1aN_M`$})0QP)%=h`u=s?&YyqnNk1s;ox% z?c18bbF72^?V5@9|7gL0b~CsxbTe4})75`CC0vSj&N*_Q(W9A=I?zbxtQoAsomQra zEs7`7l}MkL(KCnMJtvC@6~3bY14c{I-*QR+w_M6{c_tlSa+@6g*_+$fsCNFE_V@Hl zmv`gdbyoZ5MO_Y0-`BQ&sFTs=MwjpN`Kzit!@dM852&J`iJ2MOcxS+I%Q#ZfpMwm| z=BM=kE-P^e@-s}st}Yoc=xOMP6bv@ zdb*oge5GOrqH5bKL~PR-vK2Nw$E9Moyu88g#gmSfF1jeQK% zg`L{!Gw1Anca22h=_9WEld)mYf_YjO!NY*}USMh2kCCPc^4CedN?vy97_-hXa~p1vi(C_%lQl%!6})6p%p<`;P%)=i zx)Ms9pvb|%2tWpO-REXk!H?lAbu$oy$~*jQFFv@`lsVd_jGeW8N1_2};Eb%?t7`#L z$6BNseQ#&nASNF-tgl!9gI6JI$7*N}P*|X++ezCx^XoDXpW9WH++E;jdYezxZ_GVe zk~D3cg7OcwM1X4Hq>3BBenGOny{T)t%}AdJuLxM% zxb(vPY4nRJ=Q6B2=qC%6-Os>hv!zJgJjYufF z^3%UV2UaKeMxF1kgKSI@UMJYx3mGf(vfOObZsitU;V!p}v$NGcq0t<}tX^d4wuubw zFQ>13{w)35&Ux_N^-ulhD`;h&nWJu&sfERy9}NjxQ({8Hle_V!|4F=q)t(m-KtG?? zfhNcB{gUd1*aV(tqhNAuiwc@NAp$Aua!Yf~`~6I-E`nxa!aozefG?sUFtrp;R3!|h z<$;}IMCbt#S7V({)lhSLW4$&Q=*{K1S9@rk@n3`uirUlT*>m2e8qe*-^`!A;XJ=Pu zJN)Ypc1EetoeGX;lyxQ4N+sZ_6uv*o{7k(TSlJ)-=QE}Viq{%YC;=dXHXMzQmRU{#T4`y$DKDuB~G?HfdNE3mimz5xEkY9d!CXkad=|!W4 zru9|Y!sJj^OlgJCym!F4l&dZysi|U0qR`m>nBd#H1qxw?g=szPa)Ly#l=N>ls(FIM z6iqg85$(q|Ql&I05CeWPGLr_itNG47{kdk$aO2`K-mP%?k7H94@`m7-?;}3UaU`EL zhGaSA=ZcE~-%bk)VN(D0aM;u6v<*S%;Y|6oiV(Sf4 zVuzf%vf(#8v~P|=B8-%#2+agJyEKh}oBL!np!D_tG>+mn)s!grPz~t!^5KDE1ge2` z1puZ^CX+HXahR128W@L+=xp{C+MF=BH5Vn@20WqGp%0)V=2Xho5HfcqQBFWZS~Dqz zK?2JFT&brC(8|<0BZt7iK!1OKti4@k9$>=S>tG zj`OgTh-)EXfR#tE35yv34diteh1I93rL=D`_mmQVpfo+iGyq3F*P>4NupP9o9)S#x zd%Lk@a5sgSyvS&Y5$%8RZ?zg%tz#u_-SD8dH_*^T=f1#zRiXQ*2O|F<-@xmG^=I$% zpYB{~7AoJA*Vj5nG)HM>9_Qy#Xh%Egsb?li(){uQ17ehGh4a|a+yKqUR`dfu4>NM@ z&cC#$5|+vj4e{Kx9-hC1)*c>~)p@)6j>N(Gii*y13`r*RjW_dcMjul$+Be1>?1HId zezP@11^eF3U5;SzfQ)+a#+JX*B@*8^>3U3-sIiqaCo3HNsI2;^73TVzim!1;dkZwh z0j@;%TYV2xP(kHnwe+!;D@bnLL>B&B3aOZJ&JQT|Oj zxWCleVexcAmb&hH^SDO+-mO3IFjVA~P^#k{MF+)^-fG{vp#*-A*i-!Y#;bcxmcP4) zZfgW9AwmBW>+kN#s81=xE;rUEjq{xpR8);Ui@$$ImSo6lCNXc+bHhwcN_YopQ7G2HmzN(OFkgEA5-He3Ip6_XIL%>0kmMFSugoWr zNBp_uNOPt@TXnGYd5&PI$(VsuXWVf+M|u zz)0Jmv!uBh|8ne;$p9<2960FngoB|25>GsPl8v6WeZBf$hrqVZ*l&t+HjTYDk?tnc z(qYL8%cK}CfA?8=7Cb(DC`3Nl4nuR|eA&TzQxMgJBN}ET^30xoHe^!F#%{PeJ*a zNdGA7$~1d9{mkpTtFt()NPdLS!xA4dHWB=*A>j|@{_pYwd;5*061<4_{1z7$IM_xj zS`rcyyGHLiE-_AuNk~aQtD%KA3Vi95+pN3QB}|p4zQwdJjUHn^;$`ZI zbrbDroK!UW1>A=Lo*tZ>E;jz&T({@_d*L9v3`)mJGzIbX?cc_OV2Y(0PK{wPs+JEB zR$|u6&TEE_)I?Q1Kuo^My4|6v+THzB)6mhh?T$KW1{MCk?mmWmP6*?4e>1#29pl~p zQKi$q`y^$tDtw|lL^}Y*#=DT@N`(cEfB$}marlg#sAs(CB9JOsJfAkNg*Pg9d-1je zL9-DR+E5o-w=y;c6Qm*n5ebPSH}(=pGY>ZZstXKQ0&zA+?cqGprIYm|j8Rb&5~gx^ z_Rfo(tEf))-oq2jZM0ACdc{}_t%D8Fka5(NALs>=0%wgrKmZx8Cnz#kdw|7{rfghs z@DUN-^q|wkzNTTv+!ioj(Xjr;-kxXIjis$m8aK%r6?>Nu=;!Z$#vY2H z&P`j>eRx;D>(bts#v-Nf8ERrc8Sle$!7Pn=sT(FtH0Qw^LE!+tdrBGM0b?>xCpMWKcZ_``ghzM;KScJdvV5`_3$JI2M z%#Qpf=47b}tv3Cg3bI0p_HwlHl84KUwvJLUGq}qFmMYGvkV|hj<5rwy$04IVPX`FB zW58t$dY3^hEu}6gtxrwf2QlkN@hq_bDSe+|r^}Kn&2+2q`8PyjHg+i9#H;Jf2AnQ3 z*j9leLT zQFh^9`U?ss126wa&;RW@GuGg~9f*R5!Yu-zm?oH-$C4)HmH%<{=y`Bnn!4)Q z9{vHmCFgYaMDxm5Rp2ooKZ)D3I`Lv(PDO-z3;{%@r2HS!YG>;UCq5SH6P>O7y`BA? zgRS!rKtrumd10{nF(Us2*?8rF4>wt>?G;&z$e_EH4meQS*@={C#vtyKOZr8S@Bbqpt52^X$&I|TUzQ)(rYf5f+R;7H8nj5{~>^tQW5t-QXP_F&C`{(2_ zgjVPR6%`dAb6h$$POL^nZx-fHt-J^k%jwraYOR$ZXpQeM=X{VJ_YuRGJ0ttddx(A# zjjmU}T}7!Ys2q`EG+wMzWf4*r>!aYg-+^nQ5(t>ayNqX^J{rbQ0j{ric01CmOSvPv zP$j~{&vAnvQqF{ibcwz-kg_hoz8kSsEt2iDj6e(1p+9Wa6z6E`W0`xvDjdnIU3lo_ zk!FHBg>Hm=N5dPnK9#ft)2ZlnEA>-~6i}djc0Y6_6slM(@wc5+fT$B_)2Z+S*>~r9 zIA6+b<--0lNrsAeM906(msFqUBw0aPRv(mLu~{9=A9rkrt5Q1*Dg0MOC1ZO{i=0r##X-*@n^k;9gKava zc}#N|F2BW~CoP*R1v<_A!DJ;M+$k;6!`QFHJv_D`YeFpTy^MSMMHgJe97dm4`UT9S zFZFc1y*z<^o0PP9Qw@zY?K#)34#}RlM#O`h`HE&`&`w4j!L(_(% zr>Cd6dEe7E-NjmBrN5D`VdMF{RZ08QMQ_J@b6=5#i)*y=+!oZkdDfZ=^`}|KtHZ9K z|GAighwk)2O0W0ErI{?D0D0)&TrfDFs=HsWa~@!0O$jizws`jSS_r zJcC@5!6%k{me&{OXU>vW4Yg@ACFqq~D?;7Zfdu7YeUc(-5;mJwP+U7tN5_p%BZoSi zi5zmzv6Yt}f=6}t@A5&;jHRN>qMhY@>%sY|+2gwX zj>)09532}qrz#?3rw~Z$YEQQ?RmOLcfL^D!Wo0 z`bHVn#EokqWA*5q2G(&he|aAtxMqA>%_xJQ7X?C4{+`N8M$p2l+TsNt_|`FL4bJz# z2M&h%N@IF!9Yq+U76(ThNySUul2<%1Y6)S8v3|QX;nS9HqAMd zn1ATHzqQUx!qr_zURsJIU{vmn#QUbMXy&mCtxwvD7wpsJ(FO{UT?FydmGO0zb7eN8z{^Bm z@ATcm#~oDEa9#A0BP^)CuEXfx72zg|6y{a@zh!6qs|U+>F6Isu!}-7Ei$hPi`Q~$% zvK^O|*HT0&g_I_*e}R|$QY_7z_ChgPS1O7?caoGo={%h`QV_qipHiF2{`Dh33(vLf;BZ6JKiH-!IKQAe%8 z0vqH`J{v^yTI9^Z@x5DJR%R`G$G+E#3L-UlFtq-r!+O=~q3UF1;^y*lV?x?zn@YT# z?C-Q;JIct3=@P-F!DP~wcv3B^jZ=RPyTbp^Bdh-Jkp&XKg`M{pimzH=m@GB?_kXSf znn>N6bk#ShW|&9`8iSgYna3=lu#NYbZVcFkKH!lfM;Q> zR$RmB!W^nRL;egfeR)50!#}xe(c3vC4G#filmb_2vo&}>ADprO^7D4y*su(St6ONN z9G@EPt2ibnCKD4>-@e($vj$Bmw7PO$mr(=-g?Yd#K1r$Mv}TUtz%`(oJqWWUItHp- z@OT>4vSPCtqRyZ!{nZn4p5H%&6!dhmQL@~2_UsrBRWu~=nUj^Lqh$pMT}cFH-W&LP zQFd+d*6CV0FQnIWv|%D`VX~gHw+=YR^nhYb3_!E9)q}!#3+A6q5^8Q|Y4`;MFqZMg z&bY4@^Kh+YWt=tEY9FJE=7&70*z$$q=>iF;h|1h1W>bcCbD{cE{$gKKd(i)ls~LQk z`d%*;C7F5fUAoF}G^zMsPkENwU`|A>LtuQq(N!hGPmCzBn(d^fWu8rX2aKp}5iTk9 zuj$$7{iY(1VUaI-R&@_J*l~itvnZ&kn}hlKs4_pde92bv0S~rSsZmxJi?FD_rvwu% zOR*5kyt3==5n8gW$w3txQ7qwUg+m|yviOEtp)!1114sCfl)`3&SPUyv{%=`Tx4v;Q?TyxzlSKLpgFfy{}h zJ1#Am=cBh~kHBy>GIO|OVC@yFQ`uT}zw4zDKs!a$N|snIA|B{cVovpw#kCq>0d`P0 zW(=g=(Pro~LH3I;=+0guicnJS(R+91zejc1x&-MWF5j1>kSgr`9$33fWJc@6(r!#i z_Ka>6s!~(pQ&d|^bQ1rGrh;a8-Qiz@`9yV@V;Fms7hl%Uoq9RbcjT;kWi1(LK+kvg zHa(En&nwbxMO=TT%S`r~?(c5pzPNnB$hA%OB~%CP<{eM@Dd0T?0Zj(slJ6Y-pv*&Z z39fsZk3{SH`W-*-a`*-rug3EINt*g5vw5B-R!9qR4$(FaOx}Hvw&{ze)$Bo!QV$I5 z&^B9Sy*uvj5BJoHQ*EG1B8%$~@ALmeHPP~2_!12bt+ce1iqSWqqrSdgJgj59qk#tq z1d50xFGMHCc;Yi(?suZtRXBz8f@x6*U=DTzaE^HUYx{LXMjn%RK5a0t zM3e_OgMQ8J&o}<~^CrCwxcbgQ3_+z zSX1Hacd6+*86Om@ct{pI6@YSUGj&!;BL{R16lsU$lhF5gA#Qy;!fLffgu==x`RT1 z%vKru&|g`6ZGCtu)cTPP7-;C8z1_)lXAdgmQq)$Jzutzbq z9h|C7Fm*fOJLuDm9bfkLcqNreVTwO`)#_sOWoj`@5fPS1V01-&AAa=xtr-y^Z_wm5 z=^!g; zw+5{jLv?@gp*LjZ1v=*SE-Wnk{rk57E2Yyf=C)~db+rR4)oG{&(bw10lX70ZV|kN3 z%hrF0Dl3ahy0M`lF2T*}{d%5fQ4@Ys)!)BgjW#DNw42#q*GOmnzly5|M`rO@p)QvjM2c4^T=3yH9}w^c zwC-tAo@Y|N$ z;-3Rp#3S=&#+m22xf7Mqw3pqBoVHe{W3pNV#GqWX6mzR6^}-2`EBQv@GR(TljqLFq zb6;GHPKPh#74Wge&`#)^tQMn&ihz}-o*iGnNI~uv(ue6sXY;Frmda#Qz5OcljO zOS7R(7;xylHE6J!eUmXLwx=4^^3J}Q5Fx6Wuatd=1f6>o`vg@(9G~4yGZddlj+Nmc zb&gGZSBl{s+SQJ>vcP)uMWJM+Kn5axK|7u@J^G`?>5dh8hZIKY z7x9QRba`YtL`wC(+4OxadWV!L9?NGVMGjQbeMyDZ7_=#?1yrduQanQoDG8US4=qb& z^(?Rng-}}dVqPf;`7|QY>OqQg_W4u_BV-{4)cN^+fZHS z(6VgF&Y3sL=P3=$Zt}ld+ZfpKfaooY3Yk(YTtJGyKj=wFjW&BQ))tw%*YW4%K+x-a z#2lLC3Vm{DvU1DtcZ;d!oRa4iF5qlU!@*^kqPk{`a-g)ZG+#-y4@atf&#FB{>8oCF zfQh0{H)8PSp$^Nc_^PhoCH(N2^raVwa2WNY7P1laPgT|xwHyk9--h<~_SV*i-Tqs< zNa2DjpQ?S@J3A8&3SwI*`&jB@(LJ-nq?U6fwHljFX)Acv1!o03+H>W31qAr{_dYAT z92C=Bx*IG0pLyE(O3QV-$O8R)f2gh$=qsA3kl~D{XmUK=X>!~SPrL}?($Z9d>rq!k zP@!#Y{>R;OZ{Rf>Lq?XbyqXM{&D=x-T^W z!ChUoM|v==>gtTEA`+5sJiKQ&wvnDyopZPS$ciY+y9qDINrWY8zxYZ)ler)zOFTV9 zLrauNs+^F@%EN(MD{Hc^y~pa6*2stl<_K>&e|j87cV8IvHTJUC3Pia)w^UarP7p7y z+}_nnP`^voiAt7MVN{(AbWD`-D@FMlTtV@kS2gYB--M zF_%Y$y(eNwl_oU0YzzEU_@pguyCPwuTB%d|IM5OfXdp8)Ude&JWuijRjptRa1~)ujC$T#rHGLiaX=Tm7}lJ$HgjamB^|5M-Fl% zCeQQPlKh~6{M}QsCsJ+P*!j>Ao7@UsfvwOL+;h| z3w79kYIa;Dlu}$Km1R*T<|($&4hL(3g-3TgP*JCLZ*YtC$dQDb^<~X+a!TcNy-)8W zadj@e>{qc4&QE>r+Z!9>2^v(sy?Zw>TH{i(Dm~5`$=U`AN*EBMP*ql)^m*DD{=KzT zb4$N4mfsL18?^lG|L+mjzOsN}#)L{J19NCSbF##s;HOzQ?T-Y89o{oT-)FhWcab0~ z!9&*y4Nc06-ay+#QIv2N;gyWY(6v!n7C4q8!p$oJ|Dnjmi^dfZ0^<#Vjk|Tj6Z}&q z@l^i{ZaWvgdznN~dVS&3USJJ@EjE*CFP7%&2U#T+rGoskjSY-`c3Bc=j)sL!!viHv zPR1O-CZm0mXPxcOXmTI!*W7-3ti%6D=6(Y8Q}|Kmg3Nfzp7%yzU}+j2W0xe+x{!s< z)6sJ4>-y@dY(&?Yp&CG~+OQ5#ULIY(HieeIcRI|Vq=+q=_eZ}^4D{&}k@E7uBRUrP zGQ(9krELhjTe-3Ec6@yN_SSPrJ^%wZM=a@W;rZv#b$XjT^uoDsp-!Z$O>CdlTKt&i zlj@{Zm6YK5fxQDJbh*j!c-XI6q8cLTUd;N($R(ykf^p99>=amInx?E&G()d^A!GM4 zYE&eomnWnal?%cNan-tm*Oy@qE!`QLgX#lU;RE`5pecB?%bzf{iOevcl_#?1t-!E` zaYDS?5kz@=-D^UOlGIa;VnO};jt){=GBtO;li5dN)D%r1jw#Kn4*oqiLwA_pV|j9& z(+@JTpA-YBEH2n%XL~O52hF!DzbAtp@4_pJyehaC5zPlW(?4JnF59p@70?Ue1MDQe z^PI$9vMWSEKSdXEIu*?E_hQv@=mWjMaT4#T+{gjdnpP@V3yx&W2upyQo0YY$Ht3z z0TYEc3S8jepOfQ!Fz#5SqXmawDq}amOTkpIK(D*}KPjT_ zt8#*vjsi_Q?fnmwRUD_Bsnw?p{$`6fD=e!jMn+3UOY)v1PzQaO;~Q>%@h@?oRp)QO z*$RFvmiZ@I1?3(iDa#Oz(&%B@sZ@$s3ROWKyXLK&fH#*9NY;LT_^mfR>^ksG)_Yio zq*6N^F9|v${Z|VX_XU~=*~TQxB8{&gPMo?wTWf1uPwqqRPAB=^Q=E^nR#dca^j%z> zp6VpZOIQx!C{@+D)=f3UhG#QP};1#CJw2Olq)QU3|Ov*dqMk#}o zi!c+Ghlfa`u1WxuK4TP~jcj74fdF!^zsAhe` zqX2oXMXfSRgn>sLUZ*2tXB;l~g+Yc=>kTaiukQY0W+$_vTrh zjxJX<;vXE3va&!)(ha-@3~nI#=iHjtRM`nnes@+IJwrMpjoLT7HOe$kyqgL^0uWSf zx;0e)Na3X*D|vAw-fm2-aN!W_GXZrLfoHKigGC z(mry+diB$Z?Et-b3N|ZRPgmpq0J#c!r8aG}c}QO+{M$ndWukwuFTLBfs*qP<{5}_C zjMClGR+h!09M{0)RG$#sFBNV}bR;dV4k5Rpy!fX&KwQMe%d->^!iGXD5JVdo`L$KVI?V$ZJ|OZ#Dl#%d984IYwD zTR!Yl5M)hQ9|mkrONkkwvKbn>AM+w3`1niJm(LV3lZUD72iVsDD)hrDBjMR+Woe_N zpUL!Jx!=D&q_m`WDon^2mrjUc3rsehsLTUBHmOD_uT*eyQc@JvRFSqwUbj}4{ZG)t>GY4ogr%X*>^LhCju?@Fs1ZPupEBXyezckJ*co(a+b9BP z-NQUkj9Z$8_(uTUaAx`aWl0E}c+}{IJU^hrQKqi85WxLqr!VW1rUfYG3*68#Zm$jt zEY7$fB-sycV>|l&fE=?Q4&U?l`ETHBFh^CD1J!DAJUiac6|s0>|E{hhlhN84lI1xk zT9v4%pk`t!U_?p#PdqYEc5Z&EY`I_W`~I+6NnZ{%c8LII)TjKu2WMG z>-9AjoUbn`G7nc*3VtvC?le4=zF%>Cg5#0*?%?h&!O-2=;elY`O-skk)ZpOvP5ir$ z!9lh--1B>T#W<-(J1MIh69ZiFqv;OXD_$ecs_(4M_oGg)$muaN2V{}&j7Zi`j*iB^ zDu#(^th1ENt*_Ie?`mQ?DBPx%;l2<3QclV6?furL!VrYbIi%+G^LOyrhqY-~$Xh^#a8&qr!C;*BYWljut0Z{U{<_AG%ZDxGy3|Dl+cH1 zHt1JTv@41*5EtCSG^1Zfs$@`zPrRzTsjREf^b(N${LtD!s(58PMh6DWw}Pyahq?5Cx_g4O-2`n#`YC5D!AC7$d*;ZJ&wH7H z>|8AU$IFoDR9uN-Q*}*}^#DBwV5A+kU-@96e^sr{VHG`z#)!aWNeVRDAxbJ5a?rje z$0rAFsTXcirfFiu+?Kj7i?nm793efq&oE;b_}ti2j+@^(Rq<5FH)q)z+c=0c{}y~B zpCirvF4$m?>S?MGq4x_!Q(cnbCk>N^9fO+WQ-3kQzZV>2A?w9%5{v<}=`ZRXO$P*< z(Y?|9^|0fMp~WO@ow&)d)c-f&|NGm>;bWn(`^PbUJiT-etn_WGh zRiQFvw+?C_M@S>ePQk?3lTQgu%K7Y|euuF%G?dt#Q12PK%3-o`+wK07eJ>`(-#<4Y zq1zoVt*&cc1gmY@v2!8NhXG#(T3xB;@Qb!-mymD)fD~HtzHvby;5_#De|q$>m1+d2 z-Q!^%f>K~0Ugpzo*iUJ0%f&Q&C7>!8Hkil?w^+@^l42;qb5#B5GoC`s?6^W;85&CJ zJiL6lM4)?=|IX01I#e!r%Q12H+{pIG(f;i?`TeCdL4*hF{~_uv7~*P!HQV3>cL)x_ z8i%04-L)HccMYz=-QB%$m*5&axVyUqcgXE;&Yd|wV()sZo~pIprrf_Md5UzM5$y}| zhOYjg%}FZT=n4*Pxn91`rbAGdy4ub$&@UM&Ut7ysA{BzTJ!nfWOMkS1`jvG9gT5+% z1uNF?lCI$7B`MTL<_(vARU9)%__->bR(E#x{QN>V2C8*fuGHBF5%n6B*C^6jqq0e#Iz+ngw7iOEycCD{2uZdT<&c0p1sf_ix=j>>gw4!*Dslyl| zTJhH>Tx0&LV(dV0P^V?dVimzEd@RN_&w6+=uA;I_K#bOk61phZx<^-jItr4FD)fuU z6=cUC>pg6B#_ca!?mcw*hrF9^yJpob$K2MbI?T8XuZ~`d7_eKJoWuDYY0s!3v6-?m zTW)CEIN0fcD}Lvxo;b<5?dy&gdpE6 z19qm0Qd^1#??b@PKA@@itnSHig8jj&e*`BcY`H9n)L9h|4XrkDkB#ZrwFjVo6|b<) ztU6~;L{P;_H02b?jw=+>LcGkZJ0MaYulPrKb_h`_z6?Wz?oDc)Jk(DPGH&Jc^4=$) zW>d-rsu(6@V<>RoF#P5WHLS$)h_I#4yl-Ob2VgZu@JTo&a8=>Z;%4E9YfC_I=7y3T zB@YR$p~!K%beS9JBjV13IWY!tLsit+N73z7iFXXvy_DZ<(G+FWj-za4Q@fT48wul) zB%$>a@w(~VjZDIuW;X{b93SSkm-IIUe4BTTcDNOg6L1wTxu}%|Jg$1%JML5I@FA{+;R-(?1*gRJR}dMh=slj89-I@gE6Ai1$FA}(kG^{Ns4aE znwpfx9{L5P64`9z^LK{}46?OR0^(+lpJi4JboTb*)k-Sy`br2?24UV6QWdZJeB(~8 zvqi8yH3`bhh{S}){-Utz;qP>6v-}3N^`96DDzv>Ukba+7#UH{846c_FuWixft8i;Q zJUrwoD_Awx>)wF$QV<0BnP;__sgw+8dH9%KLw_RwZMQn*4Y7FM7l4Zc?C8SBz{a44wY6|=YTkPPvSIzldD)R9opkFquUA=sT4US`OjR%BH#AGb?dRB4D8 z(OI&f$9SXNl6X(Kf72u=O7mka6kZ^m7f{*K#9>yErF}0{x1hU*qPqcwa%}5p6{*XN; zKp8OcP6Gl6Us1)<`f(Uz1v-8fI|~94pb%9EehGOU6N-IlPRHLMh|C-`;`toJK@VbB zf#%&WeTb0CY7t*S(Gi=3aOoqp0Kbholl&r)_|xWyxM z0;oKYm&BV>&;oH713}anAY+#5LG_0Fhzd@;th#hvE6jUoHfnR~R84fS3r88d7oqHZ zgdpd>ZGEWiPBdK=z@h+ok}gDMR)oZKvet*z?kLQy7(k^UBLoi0w=>zhPV*?=|Bh2S z8#d^`VixcMKju+}{-~uWu8|{Ho;xB25@Jq`-`mJ{_yH8;9~cS&!kRi~K61l~$cOCW z2EH%22I~Q@=tY4Z&3$qxAI*=dhg5xuvU@V=;wQxNMnYs@bX4ZA zkC9(q*z-nt@>Xpx6UDlFJ|M9fr}}RQnrB3bm`4&qW1D@XQDlo&-s^1p|I#*^FMdIT zDbrrEdT|a^{r_k}7Ujmu=V=+h*8d$lS_A08f@ol`b1Y^!`THPQ)OBEDErH*M2rK8n z{tr0$YUWx{D9hruqvdZ6}<7Ax@h_At@$3G6J;tsMOql2Tl3JP#hsT$gt|XDOsi)mO}_@$;JMybnWEkw*xpR8~b%g)YiA^L!~&GSth=^64Ry%>1*lD zHz^XG(aCX?ZEVgUjWKet0z;+TI0G^rzktJ1lZ}m`flk@Pk%Rj{P7otH?IStzHo!cE zwyG(yZq~TnL*G!wMklR$mFtIt!&Yi@eZAEjElp{0L}q60;UC3z^CMln`@|ZAPc-qE zuV>j|?pq|1C9HsTXj17>Qb&)O9&?udI@Xb_0oD6Y<1Uzq(?3(MVyDE`ImM9+nEJad zm?iu36GaiN9iBAc*-B6V%F-TE&N+&i8#nLQmzSjWjr{J>H;0gh!83u}*Pe!UMmo`D z_q7BZY}<93Gc>G>9NU_QnGmFKn-&l4%@MQrrtpYsif~X^3QJ-R_!R0>dsV?Ag#!vd z!YadGh-W^J)f7%dR?f-EIyo?E?`Jww@ugt#8_%jI;3S-!y!NIb1&wSjU}60#w5(v` z>8Dyr>{I9yUtd9NE@Y+~%ac{nE>u+&khlQiR7V_f;8gou$DmSRRMn^RlL_&h=-+t? zpa)#6h7J)6)pVtHqV5s)G|JeHr=?Yz z@O5ovIH<=!Vs!CBD=s%kyz*-p8|qjJ*D-9+U8ZbF>5xb5WHSUy9PTm0JA6hUPg5X{ox4Zac1D zw?yGp=ft83)?`TXP5ZiDAN$QgiHZQ6_bg)yA$T!d2EkqYAH6O=I!86D>tv1+=AfBe2yc)#`ZkM9JXGVJ7(l_S$X!q z?@x{9e@`|m^G6{0cP!TXh0?%ssk|ykE$g4yhXoS~V#>RIl6Un(N*{|XFMu2)GZ{h@ z8>%dV$TZscYpW(lbz@stj}U zcrV>)zHUlWcQ-uGf$Kwjf}fY0lauE`%4<#SMY+P}`f7o3WWdqG5-xCCIvWdmDz3pk zveEPR9K?F9l%VbIzS(Y(&cedN%rphDWQFl~=05*HX&76=Y;8AkaCyzO$gO2&V);gZ zgvP(7jSddna6oqJxj(?2ifss+V@A-;;+jzZgN2^rsDMMBQ#be@H;iWA3`M%0K3X#Y9e-ANP2=5bQ?t-2 z$+r&5Tc+`6VgtOle7RcOxyd$j4*o@1$JDwZoCoOxBAP7dDl0V2 zYE_Juq~Ry|1f>rWnVNWMW7gDX4#n_upp|9oL>yPAr?+OuNCQ*_R zPxv<7Cj`X%CVX2K1qn}YF8tgE@TvKHhJ&-?6iYDhZKhoX6NL zrd-}hz=6YxupX^u(g=?#qd(2e4LdI)`w<{oo{p&VyScS6)%aP6?Tbh;czTx}_6KGD zoZx9htewo$U1v>a&T=yN2ZeTbx0NomkZjw-lbJFqpRa##f%yI|UZl~`h82>^tx73A z9O(Pc1chsh620(OKNgmhuPJLvPXO_i)F zJwj|>D!H`>R@w}3V<*xdH$tWw>@O(6%5sH__#nNo|`gih!_L1LBP4? zaA1>Ud@9Jg@M<)O0|VJEr`LJb$L*VcA3b7_V}OiD+q&CO$+qmPNy*CQNqu}EI|Nn3 z8h6+4cbC4X@?D;fq}X56zeDb=%9ELVu+aqlZSAY6=~Gw}>_#gZ$#rgLRt^ph?(gqy zrm`A_7w#uk21D%7>E?2iA+zool-4s5puT+^dVRSq)jDKD;bD`+`|sH4YJVYuQ*kG<>Nyc2@t0~WP{<5e|#0utNFTMrYJ=liT2Q5AM8YTE)c<)Yo#`MPd90V$D~ za=QT$Br59b=GBBwNoRx28eo;iB-3}95;90rF#{c7d-ukkk1NY%5)v9yda+o_{gEy7 zj+;^CB_9+(g@FZr{fag=G%OXLIjQRVF0D@X!1weJLU{j12b%~4-($I^NlF5fz;qgo zHw6e6L@1^e<>{FQf@2-|AcZHbAR6>;J0UKNG1N7z8|i_ zjQwq(t4SU0n?-UA{CL8YvYceB1KQn zS)4dV_kz(JpJ*RLW;~B(m2^i%`dmsuR!&vEo6RNzP?b`M%a;0!Wiabxl7t@}-cU|3 zTT?rIdsH#5g6$-uitA4vqqTV7sTo~Mwqa7rTd1VtNZ z+yX|jcKO#w&NE(RJBEVUa=R&0BDGZcJK2V^|Gk<_D=ctN()5M^I9c|Cwo&K%qNPZ! zn`+z2|I~+Rulvis{f^k;>x|WB`Lj_3VE`AN9#$vW-l^M(rVDR!WN6*_qHIr`!Jpb*sJJJxoDv zp@j0V<=-KxBX&pb2gU2tdHeZ5WV!iwTFUgX(Ib+Frw~JH4^6@D9qpSoV0of(1rDnk z3^42N`U1TFBd~k`7W@#Ws5r#}xgKVUDnbPRF5m3J&uaI+eSl<#Q;!MXyCLZProYue z3e`0ZjI}k-CT6ZyX0CQ7CJqpq$lLBqv&OLr-uIPx$m?`x#z~e(i06~;s_GSv1n^lc zFTfxDN@@NdU-Q5G((i6W`IXgNX{l)z38waO85t`PGBzW`2t1i^b(y6~=mj7KY0)F1 zBo}MnjR{{lIU*vWvb$emR3T$aL|i>gj0dSbKA-71*>=v-AF|6s;B;mfKv79DkkkF> zg&Gpc03a#~8oQ~yBN*EmoIJcXCpImv1e>7v%V5WS)7eH{qJa!_%>e2ggNK_{aY)JHCk`J1ra19^ZvH#oRn%?CoUI59$rkS0&(Xq zC}GT;6^$*ftgq^W#Mg)3+&Eg76+zOW0dhDNuEEq8J_(k9%`q^;uFUTUPfp^8RmbH` z<5xQa=rzO3z^?I@B$}`LcYXuByoJ9GmY)L?*p*c1Vph>J(_5kb*e5PTiMfVe71up3 zE{0|sl{mH2CnUg&?^1=x6VD5k%Rwa)mIg=rG15dbVDP0rd<8$TA#5neQaY{9#s6Up zr&tBf&MN!ix$kJPVZZ91(_kj_PR=P;M6ZYDkvM6YIR2CADc)GRF(dNH{gzKChUb;7 zb=*+Se5$)Pka4f%3#+Oxu{^j!S-pGIzxOrvj)Tg3iACgthH2kZPhLw5adv5#&0D+J&=p)l#^{bF^Vn?lVjun=Ty zj3wZ*FVS2>Hgy3V@H;{S&luQA8X-%sXDbecy8v{n7RfYan1!FGEM-T)cHjMxfyApc zPd@s&%*(%1UIro>DY<7&f1=Eqy?l+`OHa1-^*I_az7|w%R#n6&g3?Gf862n#afI=3 zzI6!CnRCpfHu=XUwcj@_Px04Qt~!ii9{BrwB#; zV^S*wn85#^LU?g7LAi~N;~vwG`?tCg3Gv2b-Ya3p|7-DlWnW!!f&U1&29Y}r#=wQf zV=R$m{`@AVdy(bfOyi1@lIAv2dDnGxuvfBAY=w_6%;?x~bU9S&K0_cRevlMO_7Uu9 zt!u4H^r=b5N?%>8jR1cFpF6oZL3nQO0*11{&8}Jj)sJTq2s`4VPqF6ruLGxp%Wbh7 zzPj>z)U{86fFT>&B*wWGx ze*%jF=_PH)4*93{s7k}h%Sul# zTpwYc4+{;o#Z#`7@$Od!Ohu2C)Bpr_Nh~(CE<-LO6uWYDb0?A@Ln1!aK2G;x75n+9 zT8uVqUu-Hh`MQSE78JaeqNBhU=FN@62}{K$5(22E0<_4L!(a(wDGajv15ww8`)iiD z%4~HCtH@Q_87i;ZbBkNr=$`POPgxBS!74(%RgW-3hs5o&i3Khf%SVua*SPa7_}e?;wvL2)?N+0R$D_}Z9q&TR8fkD=JK8d zhTf^*D1T;jR3;0EUTrk~>DI+8aVs6GTFV|8Pn8&d)P}PPd_p+5D$JGQ-`A=?%{G*q zw{bG9piMA2?s7t^cH5=pcq~^p1br8n@B{{ff^px_#7}WW6kvH0;W>lvs)vkQfmE#2 z=h&F*bA`$ZUKMmjUU(?JQ=-i6O_E;TuugA+$6`CD`!3i65vJ^_Jbt8$AlxSfK9$fGH<#M^7 z;v=_emTqi@ODM7lyJ}&~LO2q*EZov1PxQ3{BWdEP1iaK)q%5L$!T2=1`KSKIZNeSQ z&y*hM02JW5dUDwHXD#J&QZl8W)iWXZe|ufgkvm7TS^|GkP(!i`<VoV`>Hl7AI&yGV^d-cg^-UtFB6@rhPs zE!EaK*kjcD^$XwYp_f5!C1HV5!^00sSvyz91n8aZ{^Sf>tL+wIea%OMH((3%_35zT z^>u!RvuX!h$6EprS|q2Gwwc4$=H}+c#>UEup21dnPL@9>mpOhr#})C$=)8Y z)%*d4;e2~G@fFtYJHsWl8=PmN9(@o`38CB9uYSk`oDHShPej+-m%7n95vm-`_0S~9 z53ZEk;UkgfBSX&$s?qzxwjCha(n3(Ed!fjvWa+f+*NgrwNz^IFH?6qb-G>0THhvF`^5N?BdvUmG8R_oB57l%dZ|`4{2ly+yW>&@`t5gtZ8p&Qm7)5 zax)CW6zFP356rIxt8puSzm!x8rtk*qtKUPPZ(GvNf610)Fip3FHRm}(pa|yX=1_z! zP+JvlXm56=_CFHGR}xMJHhf~vF2sA;GRF)DuXC!A@ed^`;?>XDunage96L0Lh>Hdy7I_@Yb#J zqO#lIF)B`eR7>}9<~$VR_4kXfc~swQuLpK%?@d^FPxDiht&X`sqzbF;+&4%FfmDdaAYOiOk-|;e<{m~WR+DEBYgCz7SX~tSinVE0Cs|Q zN|0+cyQvB&Px{wP;`ulYu^0g`^yXrt&vZU_KWVxseH;82`b%z*(dDjzU%so<3<1y` zYp{>^Xs!{@Zq4RNne~)sq3>yCs}XQG_GM-jecb}h@W1R~duoF{)MAAyDlBQqBz!T{ z^9`4iD-$SoNr;GkxxfEA&vAEO(`-2?wW!uQyLWL_)6i-eS0|T{No_QfQ=d%0NrIL+ zu+-{vdwl))H^FPMXHWVwSqZ}lh--m9?Z%M45A2692of(9EJ`=lJ$3-e zhy0CCiY$js_gaMp>!UV90SCS&7+e1afak{`c=q0TP?WJXSdHxfLN|s6W~Iasq>J9P zsg{5GKU1Ds2Lg}Hiu9NH{&GRT$aNp7;nEIo1XrfKrMf%kd&psz8j4H-NABn^dZe+6 ztZ9Xu?A$LYUjHt4DOHuadXn*b=e3{7zP!m0Ii5-MFeiG$wwMFv`hYIP`*?;2iqcUv>{Tor!QO=MYe#tW;TnVIY2 z>^N<;+a?v(C{wRhACgWbk{oKFjWzn8GdVk_#>TQ7RDt9##DyAE@eR=8>?`Sn#8ul5 zWqt+3faEHuk7)5B0emj|lqXZomj|UFy{N7ajmg8IeENCV-$_Ejs;ugUI!)^>Csn4d z$9c2L@IxhA}LM6Q)tidYHfD}0c$STxW1=S+FFU20Pv)%%rH_+q#PI;IA?OWie$grK~YPAfJ|BcN-w)r_f7H z@Cg9!XS~4{{#+H>PLo_e5c%{JV3c}size9A^M3aWgUgj0sT9d$OsjqEAx{v@8 z_~Tx9`0?s991N;}BsXsBZx!7RR&Y+fq=iz|3*Pb!mmLj zJ2^S2R=EJFH-FzdbN=U>lhauh-0H@ae?Mt7?`COzhGd5J8uIT~3x=nV66|Jp>aHfQ zHH3o$WFbd-A{+#bq!Y%mgJ~!S=f&%8IQx>}jSuj!wka(O_3$OrIv#m#|>Jk#e~@x zw)cx#n>6~ob4!9eTBdj(uGb=bAP4*x;m=#0VlA);29smjqh40KNf)MJh%m)6`IPLa zFY4ilk}Or+j8cn~Sw>J=w-|{Ntv9O9s`-%BjMb|-WnXk(3y&z$U^;Ub(iu20{}@?% zdsgz#+?ySFj;22k%j}`M$+HWTp;!YbR5a%eM_?Y^c%dmdtj!VqJ9Wlx@f78Sch0Ws zQClnQe6Qb1g0H|^v%j1R_Sb(#fyUtf5xTg{knq+a602^LOo21Euwaj8QWcC)e*JR_ zx9T6dJ@!PV^2C|2r1Dr6J@!nWIQVST{~qQWj1eLUvK11@CI6;7__Ol;kxn0$75^qsKd0hTd$scc2SFSI<(g9RFtO*}fN%e#Ib1TFny0B0JWI>CZ-0qI^ytRy1MO}F!)yw3tENn<(gOFVaTTXR>(FNeg^ zxum(qq{eUC0AGMjI}e|Ksn5wBh$cQSEKG{9UcYiw?C_%x>fD>XqaToQ4KiO!V^T2Z z<(+qrI~cy)++1|4ChV(^T-^SamiN|+tfe}r%4?vRR=UFL3tDV&kv7QWRD!aGQLy5l z$u^Ub&{DHe-%~1@zyIO^7q_Bah-QFFq$Qd=UtFGuK^Ia|V4C|D&4@B1cF&sId%eyK zL|@bBEy9aIlSnH6xru@*0kuu1XR#bfaa=L3sin#l1c4*4Kov4i*(_%zHgX%?-7x;kzLwcek%Hhf~U$)bYP*0Trs(cVPtl~SN=+g z&j(bpN(d68Dve5R!`lUtML)GhD@HxHX=fYG)zgrAM2iFL+0CSLc~P{V>2Y9fE2D2# zzfB&0L9G95XAq}%#dEVf+E->q-f01HhOsG>h<`U=mGN_PDf&Sw{$ww~>_)>)xch*Y!gBN4!@9rhK_QKCi<&i`QBp%__ z(R)?4kWn7^P=iQ+x+2lr2qkhR6umU~*!=*ky)n#3@dsRAfO!K0O*ZZ9q(BzsW*ZT? zTE5sz>n^H0dJr6o3QyegellNzpvuksdW(Tyn~jm~<8CvWO734jpBI{lhAsck2G5vo z&&J{GMZ{Nr9hG9ceEr`^D7dV@uPah)g=F(si_Aq4(~D>BwZI^Fl^vHh7-hhB+d?eA zc+QW^5U-H4mgJa$(fa6x!*O(Un$Y!&ueyl^BvJPkaxR6uQ~&1!U0Z#G0{)^0+rt5c zJVxi2=)k+Cr~29QzA471ZmjoOgY$FJYzy%6&Gk1iO)BzQGTrqNGOo7@L%5K`iUO)F z-72a)IY9%4-r-V1S>GRrdyV_Ik}*&~Golc3L=%k6d2 zTd=OI|NGVTf2PFU_nFa?0JY!1N8PRf%knY;1J|PB`zOk_`NPE)6r9M0kU`ZpRfltq zzT}FWeBVe85QZ$prY>-i$(Tgqzi-*W^mLvznfEF7pae(G3OBG6tvOJ?%V@D*VNXRT zOGl^KOHXp~f_i{m(&oxa(@RSZLYre|W@2JwuCXLsh*Ym_EW7gLU3G57Pt(v?+GkQw z=4MY}!PzfCVyJwfjT>XV7O^lRmNU=OKsRK)va){JpAQbwNaFIFmBmq5WdWw1?OxY79PR^>;uDx%~m%G7!V(lUP4+)rhPi0UHxWJg09*=7* z>qMy1hH$TN3hj(B>^p9=NGUGgJh^~Wr<;0;Ur+#1*T0+7N(lOfBfP|pj;15Y^V!pt z64moX+c#oUaBXV(Mv2X{&aza00*@N=ukC|H&gWw7io}pGBqc?Wq0|SuzkR~zk02-2 zC1gmz6f;6-gS|w&_0jxQGesQOAZg3nhbes~hi5rGc-3_^^l@}?DYjHwYM<{j-d=P0(MxU}=tcu)vLN>B<=?wxxJP~|I zG_8i9QP!|^ubC0Gty5fJIR=zM7X`UZFEbW2#*`|5C?z5^RU4|BCjiq)*+2aCVLRl5 zC+}Qbcjah|1Z&mMv^E7mWwzTafRUa483sHoNW6z@=5l4ktS{}iJIt(}Gb9{22d{fu zHt|EzPjr+CVNXP}+Lpe+?(5I~kP89d&!c2D#QI#OTHDgmw$P*3h56zl-~Z|+NmAlO zxguF9>Jn}ymIO$#v5**KBsg8mal}TDr`Qd>r@r)k9w$}ryJ*9Apt8N&rLc)2nyZ2* zSivGAFQCs9aO8?B4WGYk9eSTF!X#iP=fC{)qz_|&{Yhlv&!7Cs&{|ay8Qjjbs#Z+T zri;WRqx3noZ~W|({w=97QlojcAf|*g-$4+kz(O`sR_PrP<+BMr@YG!;E9++Q(eG68 zf664JakN|e$6`n?3Fc3KxyBm=LCbT>jf?Lb<*CTKZb5^cw`$V8Agv!^y9C=o;#5{- z`R6nr!IM5n9C?V(VQB5->14Ii3o2krU#(cMxzBl-)aN%mMT7z_kqL6`6@OfBB?KuM z{CmP7_6b(OOh>9E`gR9_kN5p>cX4iS>zCs|Y z^4P9e88^(#%30|2fM=`EM=C9Cj6Q2O`SBs$zkWHmJ||02ppoFnrMkKJ80Xt6_0Vo? zrlzUXXO^n+@pXh&pRQ>OD08F3fp4D!5ArIx(V>9OE@`Q$2c^*(C?(Bri`9zpG;#&4 zWae7>`e;@lm3l$E&c>swGDOm1o_IrwKR)Y7JEKn#qcTGStGzm@NkKPAw)71U8ddU* z64bWgxE5Q7UH@;jQM4dX5cB>K81G< zR>kXRm_bV<#C!@o79Hz?mLy$gjemi@gX#+Y6D#X;%%(C8=knELzcgAzYPqBRMHCAM z1Mh**Hn{(r$LG(?(~Xynjt;XzNPcwix0HF}4mm{A-$VCbo7_ zGMb7MqyAR5yprk00(d&E}`#`>gjbWoAe8(A!#wEOxH>MvA>b(Z3Jkqc?3J50udkS#0>?UF&~p91dvJ|N!wsq zeKe(!v29a-CYPefNpI6A_PTdr*iUD0U>ipM*!iYtx-Vh&88giwkc>utZ|3UzFWb8O zo6xxf!W387ERfO;)0EE@j<6BdHZH1DQw7CzM-0(q;lMO`v+)b|B|S=AA$g=IqijXz zY=>6$-%GuU0_~M#rSO}F@9h`-lD8@<*|P|w>vHlmCc4TgZ>u}zk4-T;mnB-Q*N{c+ zvl15O6CZo-DU~#0xR|8q0&(DnXdh%7kJEt;mi$rS=~Yrpv+z%MON;tKZ4TEy?J}rd zGr6bHp~}8$RV7c**UTnZ`^j6#<9}=1;)4Smuv+c8`x97O6zuoJo^EX}-zFY>h#&cR za6X7DvK&G(mgeBRLi9yO2j}{zvxQv!@Ent+2TN|E>2%We&L1-wMvflAgAbw8Wohzi zaTk#XXT1Qjg0=SccD6+6*1!9b;p8t!h;zC-TA!Z)mL-|BO8#*Ya-OVkC-X6{_p8Og z8&!*~QLE}r%ha7lo^qxYcw~vR>$AaG?e4k?&YS&zu3sEfRA|9os@!>FB@oaKr^+dT z7rh}vc)r`?LyOH=0%Ml$k8vVCJ`5n6x2ytW^uzwT=?5xsm=r;MENl-0KOcfcG1zB?_ z!Zj7-ML^#S#~8HuD8-S3;|6RwN04?s*;^KAc~dd%oFL~H|!}; z*t!(bNF6~NrQw#-kyS=yJLzKLxSdJK8Y;*AgIHe@)|%kiRJ!|HNx`HuV^X1?E}`T_ zn$a~79Ftvncb2K35y-NXE-=unn2YHHdh=nIVKj7Nt`%HNFaaJPVoMZ_p`C#?+o_9W zw(09m{_7)b1p50EzU%PXxBPf#$ck#Dp2u$d+_%n*DBjihMjABp2zPzw`WKR-AyARW z9uxJDn>NXO@XmC#n{=p7j|YRU718=7P5Qw`*5DWk^Mf7 zO&;Ax+%Dc5*=C-Q)2bH)!#zgeoCT(@X_ z6xFBp|G?w$w(hc3z*DPMKdALBP@dlPoiZ3%2wl_3%Sb+m+kW(W_}@Yo@j%o!e-ZNB z4RO9{H29K2<}|p571SnU3=p01or8jSMQpE1-^=~HP;%RzAtc|UW+iKRCN#kx#dZ0f4;hY8IXFG zQOb*Ldv^46^?kV9xZLbc-3N9p4jsDLS-3m6|I1f*04*?RjMm~WA)RH0m)N&9tG2B! zufSzNrzhq~$9|7A1zFs%L}q;dzB*TRKQwe`t`c<&ph?`(R(Nn2KD{Fuan8?Dt)UiD zvuKus53vNiD!LBDCsWek3gb4L=QTx!8jKFv;CTreXzFWewcH4?$NUEbme7QY+-6DdA{g9H|X)(TtH-%a;F0ayQn_x7h%+~b?9sd1iOM+x)iQlVrAG5ORg#UYD{&m-jcNGih8 z`4!NVVpkouO8#{=1uR9yOZ!GF`kjVC8mTbV$?H(b#=O{M$k4``H1HOm=0%NM#Jh`v z(Ct4x1^s5?!ARf@>Of(r`<9)7g@!?Iiv>>ZGO1|8k7td}T$B)ow}o$ahvd%WR#|lo%vgG6Cu`&Zem<342dEJz0pB7`W#4( zNa%VY24U%pAUXPV-!z1gQiC&%sy( z`%O#9@`axa(Z_vg93WHicV-%7`ut6d!&KBsg`eyd{o$xGg=N07bZJ;9V?ke8mT&p# zp&GRN0PYsO2WFnaB00E%Km9(Frg8pzX<4Jnje^ZRkWjoQpqyvoyM+fVL-O^Uqs>xn}`0n%db_>oSj%y$%iz7A)013yl1H zFL~OG+xoxrnG&WMKkW3E930?3#&mYBd(JOFcau1)9(bk?ZhA0rdZ4j&ezoyw@GcqT8XL1vHw1tgUx=^b>U1{UtV7R z9awcYMm(E_E;XfKui3P;wX+*%pr1k*P13r@&||JP259!GLu8nny82ofIdeF7gM%d{ z2WA<6*k|P&FUnIK%p|~CnwseuD!+p@OHT}!A%oqnCZ#iJD>e-)A?hz8Zz&WhT;kGF}o zx;xNihSFt772rQFpF*sy1Q>1e6byu{USbFaX}+nZpID`!fHCU+y}iy=mMrp5m(Z66fN-7l-`-`BHGDSi^6t-`$@RAb-k&mmMfq% z{?=|C4BS@L^PzJM9u#>NL}>&W!qlM#TP63oguQt(x3Q2iU82UlGk=e84AN%#i+qMA zqfW|0g;moqi7zuY^L@5s6wA51MPKd{osa%YkkPlZhB_WWBH|*PpGIG?wHZnAPP@w- zi5$P^1~Fsic+gX1p1SiI#%1%(8eo|g1ThbdePcc+uf>jQd-FhVJq;l85c}XjlEpP$*uTqJK7MR=l3E* zHhcAQErmzcX|jOgEl-Smj$T>Bs9dA#+um?X_sH<<-PGCH+0w$*Q+KsE53JQkt^ZDM ze=iL!j?;NrL?X#s?EIyZkgy-0jy>&dA*m2v|x>Wfm zdL#e_$jxMUdU`mZCaij+%DuI4e|@sz)}^vBPw1o5yt?_(_pzf=y*a&nd%ruTt>2>F zqQ$KRDzr7mO>G1qAP5n!48SHwI)p8Oh&x*rky1m3CG=+0x4ru&ifS^CG582n+&$= zDMM*Y1iNFj!9#exR*WGSntUQe_Mv@i7ZVE8e)s`AS|J0S0>}9i7{dTIBv|-##1G7G zwB68D38=kjW2QF@@i=@oSC2-O`KJj7Ba8i_fxw?gKN~3TzSpZhY*~5UelWWIndyPg zk9Su=Mkg<00eKerq99f>P@x13stl(nr}r`j^@q&I)$@>KDmBO!!z8?UpyHxoes8>C zCa03z1XE{hA1`b`Dp2n_6X^l+>k?4}*n8P|rxL1A}ErNHz*u$jhAaA&e;g7r< zg+UDju%u9=_3DsHK3j4|f<3w|jR_qk?xdyP%&~Q-ab!&uzGyUK9ECth{f=l=H)~xg zF?WJ_(d+AjZN1gB>Q&RDnm%(k|Ne1Wd+WE<*$xm%>O3DSqOI-QyN9#@ftJs4O1sec zbWx2Sr0K0#UV5;pQqBD0JV5>AV>9R9%HrV89u-TeNqKb{TVywJfkax-&tG%#1wGec z=?62t#8oxT0~I{&a5a_`?KbaTjB*WZp+)OnYo6oU_|rnL#{36OhzsBHUq#;qN!8Zr z{94umQAQ{dztR74X^Yv5%QRP#@QhRtV7>HqHW~>K7sR`~cxXfpCga(>`NYYohu3VJ z`qtLQ>yt*|-w`!9`{)O)^#2AmwmqfBrwq4KJ+R=9btJIp7>I}!R|A1rm(ui(}Sn(g{0B^W>4bT$sPYoj&xd%Bz#rnv!2^If3@cP) zdjAU{DOm>-ed>Rfn+tR+B^1_5lAa^c%()gqU}95_ss-}dI&?DS*Y}DL2@A7c${|A)eqM-2$-Y0 zg?MRahmOmd5@#e76PH!E41c+b$VYObvjM7*+Dx;fpQ z4s%1=ZNz=oZx|;k((GY{@Yzy_gZlEKpUf8$woiigLvuKvT}BY#^$ah@GDKj=>4-!_ zn@w^@`5h0QrI{!fG25+5u5nb&6c(R89PD`B`5{*(@iWj zzynERQBqlM$0jILgyd4uyE!nB9w^L6Y?4vqO#<)q%C?J(=Ixx$*o!)&D%=_j6g zmd#fb9J#0r3I@Wf3|$5aiU}KPKg>SYR*!-k$P^SQ*Wj}#6yuc?9<>3d<-Md7bE5d( zfo#Xo7dU5PKj&G8h zrjMmml%bV8iN(Lj8+58XislBjO&blvMZ1fXU?J0*-Sk($h95gMLkqlI{V?0R*3wFw zJCGq{@z}+I#@0e!2;#ZXO7lrs=5mxEv*byNDW-AnzGdfR$| z!20*gkxTP4mY`B5>@7PZ;hCiB>(T>f^HW2 z0R3!!9;YG}++O~F)^H&4#>X&3s0E>02_W5Wr1~hb-XCod$@3b$R!5dk*3_)w03peK z&%zk~R60BB{rU4z-~3fL95Ala%&0p!#X%PrIA?xfg8;@Wyt;)=r^iX~sWG(vkp%_p zkQUsEki8+fBq8nc_J5|J17|vy<8kM8g4l5PRh4BZE{H*=?*}QJ>Hd&&tL_f}x{`z2 zmS2py#FHKO#sC9N1FZ#Px2TGL5&EedY6+tcH~^CIINzt2!jba1pn(AxTw$vx&t$gd zdaadZIt}`kUbRl7kb7BIlMb5K_Fs)13`q+_d^a}Ankj0v&F$7mbhr{w@&`=matEq# z)y=fy;_~e%!raZRO&r`pap7g2bFx~v1)i;MG)2jDOugJT;GU2WiHzm`QCcu68O8K{ z^A3rnt7MhD{xll^Nn2A_S0A1UxUiTQQFP^7Pgy=wpMW{2KoIn@nomjBi|~wHh71cL z_{(Bmf-lPVuHO*LXmU==G~E)ou-N5fmfc^o*i7KkqEAl>1ML2MU{ zlI-RZ_QBac`swR?A7QA$47bQ9oP7j#QeIG3YT)bdP0F^!iSYFwi)6#Yi4n{<%$6yP z*d7R#k{UR+NCxYbXT_xmE{I`h2A9A!M_SM|Ohh0V0v)`%pcW7Cpf9;ybhZKIYaHPS zoy91q0r@z(ktO-u{3&Gsz>73k6`!LTAYNrF@~V3R)dI6GNmMVHQSq z`u~{v%b+;erVAIvoj`C4?(PtRTaZC#a0%|goq^yMTnG1o!8N!Aw-6kHJHcHOa^|VC z-*0b<;ulo$gQoB9Uh7)fT`=^&nw~6fvnv+~o}P*Unm&^`!DNndYN+I-{!`1Or~LO3 zHWIm-hQ((3s*EysgL9*Sj$Z>sNreLb_AeZfLJCb+%oqU}t)jELY#PGPa_h>qp-bX7 zdC?y#2=*|qqpLrJD_NF)if5^k|y=cHj@ zS%9qkirz^}$Z*tv)3A3eH^^h3nOx^gGPB?KE^Ko=L>v(7rYT&d25jaBb$wTnO1b~< z1&Qf*01{474Zzj$*yd->zOMaa7Yhw7{LA9XE?F00{-R@>mKQ7SChegwc^mXoa%TUX z^*MRSNG7S(g}1r*&Xa<-7)l=xr|#84k~p|qMmgEwue-f7JE;Bd#`O08O_^t30!fF6 zRzL)RzfaTBz<)RpZMDZ5vr71AXH5(2Ov8c90%gu>OC#~_gd_O}Vo|PD>{zxwh*t|uhDhtT zn!$})-KABjWhv3LeX6VCR+u`fZ+(~mA@bvN&(gUBALbF#cz#-iVeA;%rJq_KG8HPN}F-xRwn|E??_ z8;s6HS`W2M$n!6xTyb;i>cSSlPB(mC1s1W(IrI3dWxs9cNi5WXw3G)bV+qAlt72WvTrB-yrwEj3&XKtx?-fuha(uf|NPmWYLXOVZ7Ppw>FV^5o z{4}(*ltsqqWPUDc3Gdp##GLQcXhlHn>m(n0(lPZ071>1jNNEu&I+l*++X_i{p^NBX z)}kw9Q@e20uSO|bmh0R{Y=`4#MOXEymYyRXGw-bztt%f;@3ILwY}zjVI346NP8z-Y z>&neI5D-02>gjK$7OuXhh3Q8S@ij)eG6erqhM8K!2RWtELmKV4-+1jh?M8pn#lO${ z-$g13POm-ZKJm#^Af(k}jTiV%Jr1`MjAYq{B#rYF`0yHsKvFWxGPS%qH9gl%#p`!` zN$yltib5e+ih9Se^N!en7=8BXJTQ?Chc*4hakPk->t9Z4t8F@fO(*GTNU2eeU)?6& zm!}C0XnyE0!E*f9{bT9Zv!GSn+a*g>hQ8&q+E=nl_Cbvz@xia8JjrmGsl_b^8u7Sd ztHn|5+ob&IL#@$^0IAsj8z{d?{rv!c!@||+ROrC5G}yfvJGH=_YT6g-{5%UYtQqXj z1Ji_NUNIMQf>a~3)9W6fG>Vv z|8MXXX;PJ0MHykCEbIc0o+N0PpR=Xxbui=s^{g(hY3G)*9YnpLqX)b=Ag>9rEhH2F zO5OfEXYtu7+fF4yf2aj)O43qzTt#dUO>$BN>W4abmFcIew3O=nN&7IC%%4WYq{e2? z&#Ul-hW%=c5v^923tjb2=eicBVrZJ6z)6zQ(!a)!xPB^(-=5_8_O{JBad)qn%{f$h zd{3unO3e_YHCVWXBj|1AbuZ`?JI<=fT+il8SKyov3lrD_ZO1fqq z{agALe>syAOIe2ZLOKIEZjR==?Pd5Tsl%njx8s0mldpD>0GI1ZW5)ZWH@+G!N))!4 zxh4TvILp6B4d)3E)#oV{id7H6nN}ECW##lSJ>Xp3Zf6&%q(brX1B`Gb-ZbWZzo45oM#AR80$}w@0WydG0OZm=c zThOrzNWcl8tNE{0U4ysKa6T3P#;KYJZw#JC)p~!xmq{9^MY(GLr*wHBss+Vm9>Fnb zO2r^kdraAdU*Z!gm$EKHADJ)YW_Gdm zLs<*Q+xN;|gR_+{mHxTQJnWZgB6H_D@Xl`nM#~^H3JSmjAsHU;Ex@LT;QS`&W{#2}a7;b64` ztbmVeZnTJ*;?^okG=Zajp&yx2pk0;hG99AQ1Wd?8fkLXUUY>s}9%c(B_gOUD>L2@8 zqF&GlTX{be>?GNtXBGgGus6&}n#eSz8rK+w@)8y7iI-N(aWXuz0I#gyZ)&v3{Uijg0 z3>}~)LR?(-+K=Ih3al7E1c0$hLUoVVUnV>TwE3y8fN-M-|G`i8+w^hb(K6koYgHTw zf0~sJDzOHa0l$5_w*BcT6_tbcdq(Y1J}EI_cI)f%_$jq493HM>TX)WVlV7@kaHfyN z`mk}t3Ly##0j4HU6{T)mojz-IU3E1#ry>?>(*YNfTz^|RPsPtT8AQN#i`B(=SBA5* z=0vkLMnt3RLN=xKL8lg>N_>~lBXUIA(|z{PU3JE0^V@PZwQ1o{!CNs0muj%Enjf^l z50d~@O}$CbNLuciBeb-lXh&o;`_3U)HJg(pL@&u?3Dou3h5|n}DH_!dkvu`be_9erv!Q`n@+op15nsr%4R!@w= zjU+@^X-#ZVL>D%k>{#dG<5AI-^#Eq^{A3R`VA2wpze0n zzlZ|GJ%hEDg=0IdmXZLdveDEQKGFVYvbPqDoJnqCw}1WQSN0u*Y)trs5}6x+*p8?s z(`TV99wkP(q+VV|&rD^uQ3%xPo1Ul;X4)aq`w{HGA~s>?_zV|iDwwZfO&WqxQw)o= z!rN%T_yHn@FU?PGwEy<(RiZQ9f8;No6t{NBHoO<^eOXD$R9HLYie0M<&mYHb=xUmF z!9gsMYU-*b$TTRJsM#4hy`m^5$6!_wT-$Ulx<{3>ZslOg^57RgZ_Mm_;+h=P33b|_ zKSqXWnj~nm?y&tMFO7^XPtTAj04NAEO$9uhcWilT6pOp507}}%9OAUQ_KZ?R+at-u z+B`pS=D%|X8VL90WP?qFq$LOcI*ADOP6p^c5xrn54H?yPepKhCT50<%`}uK{{o~O< zntidAzB+CK`@JmMUeZLovy&4}nR}78A};omP{H(<3-s&%oB2l1HnHH2tECW_x7QQA zjJP762+S&X3y^?C(?w>LJZR9<6;d-58dvlpi2tlQ-vSCy4iV5T^Z0Z*x~l)^_kmZ) z4I7f3_Xz>QKQ#aA*wDPjAjPGr(VXcC0}26CBSC-gY;1x{Igfh>I7qne;8BhOL-Q=* z1z~Dhti;{5*-BW1#$CPQGRyPcHK1DBdnyE#Tg!ryM`(LSmVTw*C{lXv`^%xJ^Hj(t zi9C)q>V{H5Wo3y+SJ^zSs=)0vzIL<%vcE8G z-UNnLDY}lE<_Zk8+N5y7ziqWQUe|V6g5lSBRc*Pi8Q^#`LPq`#|B*T>m^2jzg+!@tW6P zCz$qTAQq!JOEOP>67|JG7jLd7*Ux4+ zph0e2{ZRe##B>H%J*)5UzuhOOWsDw$`Kz3#NJWv4wa|7Vsb?Yw|JHhsw5dB9Bez(b z+le?qb%M=p!{~0UW8vhal$vtvt{0 zR(r}V*vFu+OlHTm{44c7b6Mks26&SBy#&p((BeOWsiN zkn_xeo8xXLCaQc$FQzxTKZw1D_axm)O2-H;nAwJ%Vt0I$!M3s^qTB&$<2e?D| zw_Y3}JJ$Q;C$w3Fuu+}NybtOLWcRqA!ZW!{sz@Cs#fRd)qsSv>`jni=ww4V|v->zq)b7M+m zr`uLdO<3bM26qd2L8}sl)HcO=R7%Sl??b)QNp5X$%D5p2J%N* zNao69zWGRY2AUrHy4S%wX(R z(?glYp)bYHDgdz5%E_Xxo@$KA!2xH!-nd7M8ga@fsiBIMrs39O(Y2yvkYu5*H^jtX zqO2oh&6K2J!<%R|Cth|LzX=-z0vo<-(Pj3k)z&4Y~S2Gts`iDfz_D}{i+qb*->R!~ztt-Kf^ zH3shx(hz=M?ZH1z*uP=;NqXJS&+QUVl^8$YysA*_SAC4Cmo~r`G!<14_HXM3_0faH z^v#8-l2EzhH0ASo`=rO~ZM;(~4Be+)dlzJ?k&d9ts8uZ{=SQ4HoIfQhQ3921^lz5# zrRpeeXbC>N2A=C(Q?Xj^b&Z<5)6&|;ezza1wOmN&238Bxygl^(mpmfyByE=EPO_(G z5dDhzZS2x3&Uh~S@^Y*HA&B$;Qm9xQ-R)AVW>TOzbamT#Z&_;cTUm@e-^ zV5dc_6+03zQ9m8;>hP>T%^J|{fCx;sIIaN#;_b(i;F522;2a`g%6@X*qW-#OcHEX6 zNSUq%1h7FG<6!HMbdA*MI%nA=xL&IgZeMmai*=}AwK*13k?ig2$hZ=rNjLrt!4C;~ zJ>R)}^zGE;$$)F6h5A9hF!3>jWcH*3Qmcu4s96vX0{N%@P$ux^tk!~7t>i&Ok;S_15e8)mc` zM^2ZLeU)FXr>TKmR^WlkJ^KLbUzCJa@eIScYWb~qY=N%zFudrIUTLhdyHi;iZ!}y9 ztf4rB@rqykV~byHgF&^fV8Pwpk@qKU4Wwf~M9F1+qKD3LrX10D)xNL}5yxY(f$MwX_>WY6ss+tc$xDCJj?7yjmx$Gy;L;b$HF+9APjnJVv zIKv6;AwL&k7qFflQ_MTgP`72W>P( za%{9q5Os%$DwOIy!3D-P3K7YER~5%9%d@(-!ma zNmd3;#qe`E4$Y^rpE@(lNu-vOhjixIA$|7Fi+g~#_J+oW(e9-g1D7fGCGhvHvE}sH zRJu^AC6_#g}5i39fR=nSGT2>8xsr#Bod^%0TcV@hp4WA6{zQ zrip*P@-*R#Ot-jdZZl~fIAs2_#fEgkvFpm7$TJLb;11*FTLk(QWgVUV%h|(O%V&7s zzGzKh!T0CoFXPy=8G!HLwA-v#t$5JlKPpIk9Z7r%oeZ-G%m0~pFYqRu(bij4#s=(+ zsXHD-WsUq3yGV-%kq%){cyD|Ax)T2n)_kpgA-b_13!a?T%{UED=J@+1%9mFNC*N!;zyf`iER+JLHIxVmYuekLZaH?T zzTC)41``z|e7?SWpJcd~>pH4&5FxQva_-Acfg4vNDOoIFK{M_`Fv))Sz16MeP57FZ zdpWhd|r*)!Fsl0r$)Cg@0qsR%QfCV{DXsu>xVmU<2ncr0Z z=4hw{mLXF1GKHQEoo@Z?p7yUeK_q@q&&S8)ChjXXj(FujO3Asx5y07hdj^}tCb5zi z4L6(HiG{h1Qsp}2{)E7aiduGtKo|xmj3EG zMk^A8o8PtqGRli=(9avHql>gWGM5*|8&>T|-E$M~AUhiXJj1d3iigA&7G{6usu*8zi@)#Swy9{#H?P-y< z+UL-D2XQ!^hoAL;fV|x9&ezKsYvmSJsM!uS(^Hp)%BRR85WRIBG=?YbFqK(qqx;Jj z|DYgO-)5aE8Nmn@@OTLcX;@61a@l1{vSWm7yI~DTXc=s@l6|1EKpF3E$&$9Wn$kL+ zuF?QvCnA!AF*~Szs?xpC$P0KvvLiMn_IOT@QzKqn($m!|v4dfJC5JQ?`?J8u-b)E`0}^508$QuN+XAB#7R^V85^2;!{&t%>7t1z9J`%52y8I zTIpLtFBN#@Mx$iq8tB9{n|nzRvT=FTtp?xRf_-XdDdF-dxlLn`BiikpIwWm&SlWq0@cL?w!1FDA7UWrmSF z2YfSXH9ywP5nEkg?$7pV_gO8Yo`19O2xbo#Z`8)~NGf6kYOf*)qfTR-lR^MClMr0| zzntwJh$4RD$qm2!md#e!?UtXbI668?Yq`2|dyk5fJJOkCxNR2dk`%H;Px(k&y?5HS^{>cMF1Ev-c!{3FNs6OzP!sGdY|pSdHy7@=v9_CrWRm-CZNLzflD8eX_|z>C9~ zAD;AphNd!bvB+~%wl~G=H`DZzAsLRWjL>ibB3;a_LNETh=Knut_*I&k|G(*$gm)oQ zEwILd9TB=?cZ~iKDv1s?th|mm4X@J%z`upUcaI<1qsRvb*q?}C@>)BwzkxFU3So;Z zsIpKIfRd!ARg3ZJz*`#B8nAGT0DOVZYW>?!FB3V51;5bpTTy``G?Mxh_3@VLzRCeksgMS@GZobwMrN+CQfZq#bMh zXB-6JU76D2j==B)igU>zmSLzMuVxm8%|?4yj|QiASN-T)5Hi`?nzJm#|4 zTBxGK2J4Wvzei#v`%+vOAE@DJ4CvB`AI&BMoxT% zp@c2Q+-ARp9SB)h(u3#5lp%IYRR7i-_bD*XV%FU*Ky(+Jk@6)h>ZEJ z_!`swW{(@g>p5+>~tyxGKlMm~Pa717r-&06Vul~z&VzU!m$g)hRf?n(qUlTw7rgrs} zR=y>mUb-s@)8ILcok?COjf*KweIDCd?iWEJ%1Wq)hYAAuG}N7YVN}T(Eo<-mUOW9dE?{A1|z_3EToG0hNWOB&` zCmrUA#~T%g0ddT|$h-G}43gjDR(D3SbUqr?@si3G|Gd0<$mY=K1K<4QBsIE$;t+A+-7vx zjK*5prZfR`9<=%L^#AVuK`#>h^LhsbUzi~7R>x8ISBIa8fZI9k(Ez$XUBrMEEdXjn zAjg067c+#y4h{td0VEJ1{>5hF%OFBPw-Y-w5?;S8=)lxZa9YJ7sgNvq3`G|Hv&Niy z47@s327UADfwt381s62$;3;bceW0%~iIP2+gu0T^&_|>qq?(k>avidsuAZPTettn$ zueYav_HLd2UAj7Uelz79^LE&J+S$p)gf~Bl@3kwAXfJRI9EdX=ejEo-SvMTy-9`-WamU=OK$I zkVr;ob3lg-jlPX~8t6*85WvzG%9!-udYQmey>-i;xlT?Hxw9t6OzS@7{5?;1ubknt zk&7qm3N1p=AC{JHVuw?T0yR3_7jptaL$(^OL%5ETQ31~=?rfVEB^V(p$oF?!RN-RS zUI+$7c<)4x<@y>0p#uhQ?ceXYT5&a_B}GJjF4R(LrMuN=sOeLCf1-}$@Z@07%{__! zP6M=5Y^fAv@v)Fw?jNbdiTct{xh@(P5D`M6nN?;Pqt+>6V`lwhQ56Qo7P3bp^NQ?e z&vu=$6l+t@%nDT*ADxUp!dAaZAeKLuBrckgJnqG^w)TLbD_akA<4JzjUd>;=BeRa6 z*y85#kpGh(2w^aZ0?^J`3M7?n9`Z-{PHkb08Qe+)EH=)X>V4v&^r;;?p!0m!ZT2$} z5MB4sh%YEh<~`O8jy{U?jhZYM$-hp!1Z%zDeW#P@dG)nWkE#$=F$`D8}SuJ?NjRzIV0+20~f z%bnoX6fx?g+zEjPs%ecFKIF+B51+~)QpW<($K`izYA}=AAZg)$jxNU8M?CrAqVXsY z=zG(R!C>)^HIb5akvmr6HQ`!q40quw=ru=dSBTqDp)@4Cwn?lOOu`%Z=k1=JhB<^V zAc}6x3gH-N<7f#`=srBODBpa0N{b=R2z5vIvd2yS*d|bl zf-XMZ{@?On^QOdVIWh9hgwX9twaO z9LPk$*wfrNUI{*7g6A3@FM1;YGr-h+Xt}cscm75ZkvPLKAc4N~90Q-|cJ(U-^qFeV{ zFWIqU8)jx^>8#))0R2N`A*QlscGzcz5f)}B6lz665S)pIg)e9gVNIzXHNH;0o3f5A zkBrNw*!+2&6rv`RM0@ilV%$GtDZCVhgR1Z?xBR;K4Ru6}9L|d>%2;Uqj1hVvo$A+H zoFmL^5qx@j&@=K0LI&bapYX>5T)S3)={|X;`o$m`q-qJ3f=~nZ7e)6iQck$2nFO;m495rHNHv(#(I9wmrJp;i~(Z z)SbZ;XOKEHeiw;NoWAHb>4wwL^!_WEEc;huWTpA2XlxeQAJ>lEU7w`)hUG~;k!3FH zU2~BhAEjrl!uGkjkxwmvZQq-aV}1>2+Pu}3pC!8p*y*1hzR6?#ZSKgVH2*dP$G12C zp;7DcBUy?PRdH5w3Y|L{j)w^fFi2sY4lzH48gGXciSgv}GG1`(f^$3l-wL^kdFZhj zm+0#{_vbNz;Q*3R=3N<~5W((Du5GHlkrfv_sr7udWS%F&`7`!8ui^DP15*1RD`PmA zU@M#>k#kIHcz|~xht}W-`DD1FfJ4$R6-bBNpG>{AC*;t9^J$7`nNsfnw>b)y7KheR9v{QJi%>=#NLvW3r)YVE20 z^8hve(tvv2-Typ)^8dH3Oq>hChCD;RgSl*arVk4?(V(vs+E5E8EHkV+n@P}3G6#WL z3o;N-90F&R_RQlH!=}U7Xo6nbU=V(eP3&?AoOLF{C-mnaqZ0f{6M))eLtd?sB!!~=G+I1r^b#_p7kw)M7Fv__N> ze#l|-S&gA&dR$88FNCSTrP21Putt0kaGTt(f+7qR-E2%ro8}htPG*j zKjUOX++gh zkBE!h@c z8u#e1rxBBkv2!E$3Y&Bhi>^tY(8@kboivqPQfe)}&6_A@fMDB%MV;Fk99Sz(gJ;!M zKDJueB{&4k?{sheykQi z+Qnd;2a3*%a=w}*Ms}g|HhdB{z$8;xRxli@*~!ClrEIJU!uAUwV9({3S+ClnUFv6< zFK4-802m%=ShwD!+U&}TI)P==mk7nvMX|*z+p0Vxh&b7+kKAsAB`Vul^RAz{9pZy< zVZURNSbsTnGhC?GZ_Rl4h|Is-a24^W)wAK1wDpB=zxhNzyr)A)yDk#<)K3M*Ip5{) zhZc6HsiiS+ENS-o#W&<3q`Sx5t~|W?7F#g3Rxtp^pS=|0n!?kODh5fsI7TOr2K?F3 z`29b@;0y|EtA>Hh1Oiq%5Q_{Ba0c4};+X0iPErTHYZ8 z1F-%}zW2GuOPKyqSG;$Vp#tuq-sEz^^2HKYkt=g{u62<*uEr$DWmkRjRt6!d~qTKwE@&=o_t-@#@o6z! z(+*yIrRq~WoB+xv?U2RW+i*c-pc&9*Ga*Gj9{!P#AWMUaPLrZ11QL&xP9$~)np$mF zy-kS?*w2sh2j4P_Hxx`NeR1|@$8fjuH>j?5`@ZwiT1Su@Z=G# zZ@Z)sH1zi^gxga2RN6??`2AON#OClYyuWkCMAQ5zs-zv4qAEwc#D=L0CXo48>ofT8hyzVQ1G~~_vPbiTjd28{-;HXO2>d6T(7-;^?BH#J;(*Z; zL)NjVV`QR-Sk`F<7z>`QEW0&hgJ*tLO)kot^T-(syFW!Yis_@1{Y$h2=s zbc{eP*0NLl_^KD8ayRd_355oVeJRHDwQ8`PRv#f5+rnwee^#K zcy!(rPX36fV!3qr@-p)V)mw(*yt|Rg_~u!r37hf*55vC7-wnLu|Etlrzb>jE&xbeD zE-lxA#E@8P0DQ8WdLI9T3~iK=ojsHX79azm5dTFKAdhJS?B?VN;z+k5n^YMlS^VnI-}L9k&!p$NcBTEj zRTd>A+oh51T_+LoK@(}}^wdr{5w<;uf4ys_#zwKDved@5`8Ru`*sRy zA%1=_F)^FuMM6Tt>rGc_9SU)4rhBtIWRv9I+pV$lx*5?4nx1>Ugs+9Yc$T!eKGM>K z($e|>XzY$qZe;8+YJ06fk!iZup|#as`9xdgtzC4;Y@t_a$p@D=VsQu`kIazP%@o1L zKLb85v|5E(Fc#GztowiN#AyuaDeqzmh_b}aMt@V{cWqM`W*BooYQW4(YOM#(G|UbM zp)vGhA((D4pS%f?3gSMpZB!2qm!xp!JsnRjOPVMmE zGu5QeFRD*2A%==-8DXC`7;9&*_=Dm~N?!iSP3s zQEJBM@UG%l_Dj+E=F$+{6e9EY7+$@HvN_$W(fJJCx!sXcnF~7oc2{DaaX+aCcDaMR2Cidu_GH? zOg@zOH7hPbFed(Fylpm?sL0RSgjw{pL-yOZ5uZWljnad;EO8`yo?|z1>veARN`d^S zdtUj)7s>>w`DON?9Z_kN;~_Isi^GN-Jwe2{fDP<9s)ED{gN~CF5lkqUfT#@kIeFeh zZ)^I)OBcm>6WdxeZT3#n>gKN&l$?&;N7?I;6p85TX^ zKY87r_NOeUg@d1)AF7!{joE+h038u_N+UFAZn{eyCUgVt@q4{OL|~`pS^#8XnH{4! zvCFHQm~QIVrY)|A#b}u7iD1DtOpG;I|0_ZVCoE9q#xe}Mi4IBy(^E<%;I<8cDT9x8=}I+%{^8>tQ;R-6d=iMYp0E>RGFNe zpRiMHV+*(YVc(2dmE3R44-Q%px!3NrX~nyzsG1)M<#|rJgb*kve~qk2#EHNP9L}Ef zv)zzh#+pPXV}k!r>0^E1v@6rhK1+6EJjREd5Ga?PTKqr-r8K$H$v5yq$_(Nq+76RC z6Ds|V?5;ip@|e-4Q(#agxuu^JNh19|Zn4VAPwK|`N@Gsco?-j;_DahwM1$cwbT60| zpN%puz(8-hdqT&rB(ijg*f?wrl@qm?6oVbyszvc)*H~ft)wR4t%?1%SZ2mB0LcSP+ z$j-2G6_A1c;{#<^(2-fOEz3#D8Di_;?~E!WXm3yzUNn|Jt0V?h_&)GHc!TxXtxaIu zbo5|MN05&Xkp;#H{6;d4=#2y4<0ZGipRFI|?ujHUq`&8uDfxZIxx(mJ?Gljloc|oj zrqo`qT+?kr<-mje8_sWB?^lkRfanL`hRM^D)(vGyYg2n@4Q0A2Tp4=^5Zp8U(egX` zzHFa-Lsc?@iti_RAi{7Gnj;=_P0CI=91vEt$!0-gJiD=;f&KJP;!2VBpp}Ltl&FfB zpHSkiBO3#x;IBY9mLo#^?Dw}j^v4JP@NWLf=?G&cv$T;E6wy~bDa%C#S!*~ecqBJj zrBE9|{uTeJB#+P0JP{T4WC>}T?Jy1p`KWp+d~xS{m8nQTuPb9oB|rSR*Og}YmRxIh z?`C++D&^Cr!Oe0kp({U*Pur+x+}_9KsA8b#ai0HqGM6ymh1!J_)0eoRL^CPPal1UY zoEV|tliXGiH-pX|+bZEfG3_Gu*g51C%U}HqYpGYxqp%~N?&gb|#Q#*#|4#2en;m~? z`dbC}=H&;y>X@;!qu-EoYzC@8;T+!~IVhSlBCvl7POP42vtSP|=*5hMy#)fgyKw<( zs2nsY(|PF{{qx5ZaO4>T1=#Ye4&ZC?ssG{&eto@WP6ofS6+s*__BtCVz~fNKvCEOF z96UG|bfdesiu-Nwnl=oZYrx0N6YTEl%UG8>H+SPhT5fyDzXm72q$9~2@?_9v zySu{;@pA(33_?oE9Lj^o)b(7=Q-P+oW>AtJyxt8z@#wNI)YP0AcAL5gesdHeSIp~y z;|k$o=vsTko~H=ZQq?IVaiSwajPyU$Y$d!-e5Xx_`XPWUP6uI(V!@ArYq|c{6iW$z zmW@(n#_&Wdq2=Y)21$A=r%kSB_8aq$qSC1(r%l1IC9Tu61b<8O^=g`jc@%YN4Kvg? zAG^{GG>4`)npZY)dV~I=5wOWCBp-|8K4RS3_eCH`+3*rNn4vNerxpqt4UE*cIok-& z&saiSKly$QD%(i%J#}nVh`3MEwx-0K`&1lDauCaYi@G*A%7D?gg_{;LqZZbJJAz-# z|DHcv_TN31An1}y5+_DXo~lo+k5)5%3;!+(>+Wd!K0?&-{9UVVP~cIhf0t724ZdeLeuM}5XKRz% zamq*wG3AP=@viyaEm zYd+{0G^$T6OWxO~D%R;@b9R3@NXg&j6bso^>>{`DXFpv&??D`Ns zEQjkgVjA5xA~S4jaM2;9n5|unTEOG*;pz;T-JsNo{eLC*#rh>a7PiUsuj?J;IVF?l z4K&E91fnununC34CbNnE^A1D{scE5W|PU(}&6 zA5U)qBNnsCtD1`(9*|<43>kL2x%w_IudrpPz;PMOYS}3<*e56Zv4#(OEiElI`jriY z8P#k@OsOC`)IcrEY5;vpz1h>HR?vJbni4$m$;f#A_BvunA&JATVvohie@@9FGfe6| zD%#!s+0oG#yOAG3Y}UnWPoIR`2N-D8t9{UT zsEvc@Xae;Q$Z1AYnCCY|u1RdV%?T&%%smcF?APIKMkwD0R@ac!r^ zMX!BvkO)*CMkVhX_=#7>fu8vHkui9WcO=Y$7=bC{?clKMO}>$Vh--WKH*P1!$~&!< z2xrpgU1^PFVe&rnWa|UY0jh|zq}zx%=Rz(`NjTLC|4KmvL-ygFvO^VyLvXs79FykM?+OZMEjPpr3acreKy4RedAK4xtc9-s2D+2b zBydJ&rOWorWc{N$d^L5(Y)V>DMcH!bR0rIxxZDrZJ8PV5^?1D{a18l_IStwX%yXm0 zjS-{VsY5%E(K@9W^h((!vQWaTw>eQ^eUh9)pj!<-_t^DIbyEDaq(V)Cxp$m~>sO1v zyR!1=K6S4Sv2MGcVSN+&7S+#`>6Wjy!{*E`()Pg$*N^$&DbZGU{fA_RrkEct-ewsV zA7SH97{5vqJ~e$ceSe9oFe0~DSbBQYbCCcqL71=lEb(cGNq=3ec!6>B1lgP zw62)Ng*;PY-x?GY8l`JN@SQ7^fro3?ZNS*H_V^l8b+_>0^RVH3s z&Y7cnr}#0W^_r^WoPU~YDI26@!Uk?+Xp}?J9_+=;6LjS>Ww(m zBFhC5-aC;-9$Dcv0%Zoj&Wr+t`9I$j7VqYd9YXRT2*B#W z5tPb4Xqtfx{9)?v?+fl~{ql2pW&KyJj)-uwHe5%h^Q*KNmJXlt2J;0fj5pR-(zD*+ zz4`Cbac7a-0V~_zw`d5*xUD%mi##<%0M0mCHW|anatx#F9NgTL(QeCzZb8a$#;z6J z_4pySuqiSOZcDEtt28vMuV*7d51-Opl#rBs(p68&XQpMILP4hF^AsGz@XQK=e;CNs z(hF=&PFAZ!feCV-g(^Q!lCU0van{CG{%%nC_~WWa@LkjJ5{3N?@$X8*VAGzK8%QHj zy33w($c4S+>ugbHc$r!0e zkrf;wV`Yv74hK7v4oN+_I*4rl22xQ)YBt1~XkfIQV@Q6`Wb6I>_~RW16Yhz3*~-?> zkmFr*474Z?lsQ6qY3)#Ur@UHi>YnI-OpLeB&XPE6ApTL_7lR{>F*1ljDG##`2bJ<@ z7A^F<1VIWr_=ShC&^zB))!p#zA8eKPf`W`ASX&rs!lt@ht=en0`#(5ZEe!JFJ_gEZ z^5>G4=2==8d{|s2w(wSpwTnK%xF&kJpYv)ej49K<*I^~pX)|( z>l-^|qBlz^y#W$F6ysy00NreC)60N5<59Xm{vA`A$$I~*GW;YN`YP%xn2pc&_t?SN z-}{z#PesBh275OmyAVdM7oI$U$Xuoy`-|(75N$}&W7e_j*xsMJ+A86rup(C*iNx#o z>ZUphwfl#6&#ZNjovE6EER=4A1VfcjwqOPT;bj1&aK!#-J!iYXaxA$^v=n{ZFXW9| z;~!sq{7A_y&UaUcZv()JX?$3J&akQ5na0W1a(f@-0{*7}{RcbSguC>nrI4Y9-QXD! z$LHoyJxVw#yeQRdocQ3x$?!>*v`7Ntp3Q~_r55Q=yT6ct_|G(7E0`U7ApvmzG4l$2 z`2eYeZ&RF%lqFGt0UPkxCUh)J%jtghBBROaL?;08wIR?Pat7^Rlr4XmupKrK7FKWI$7rgp!z_2lIR z{RKTL;03+Ku)DrTQmU8N`uzbMkOm(S`_tH<-aZdjq3~L)Im@oD&~+J=QkD7iY2r}J zQv>^m9P(YdsNR%2vueRXOW2Id1@&?7i#;kiTIsC(ZBpKk0>ac(mzwO2s-KgtB1pX( zMykL4KL09jb=g!`Q!_a2u+iblZr6|q-rY@2P3>r6Kh;{aF?OWV0$sxoUxsPTwz^r| z&m_yC5J67`ZWt-g*31C!sz+L@@Y-JLY{<7H>7hLj{4!%uGS-sMHy$evT(TB~44GMM zEL$n>_z82EP~0t4Tq&QrLy78khlb!s_{B51b(kq#s#S1PaHJI-j@tF7xrtwNjHzRG z_1BY8f7y;atQ4*ZAJCt2RX?J22z9U_e(uZuITymL@-4(ReEBS>LYajloe#mWQQz|? z84J^eH|hwvrqRcW7sYM-jwk8=A5mxh7j@KbZ90aAp#!kp>Cr6zK+ucb;=T?{j{eKVa_f-h16^T}x+rvO{?mw~}>#xljiqjipK5 zk}1>7i$3$ztzndvJ>zqZ5EZ&4uQnh9qnvuvr|^XT`;Tc`y*FPg@oGq9EntmWS+oS1 zut13@>nTT^e+9pj?1Jq^P`vY)&vbo6clsQt61Er>*|uvxlixbGiRJp{;`(RoL#JcE zxU$|2^VRWrl(FYU>rlwwPX0;wjDeP-IZQ%R9j6}B;GDsiK8cs2r~6wuF4dBUD5vdI zp5sxa$Go&fW2Cb+H=Z~;vf`~RnU2O^D;8e)eQKHTJUy3;ShAJ}43Y!a_aD<5eBLO{ zk@3^fBg>dIg^(@}1+t;Z6CX5lWIT~yxC^lzT16E{DVL!sv)8iQF`mB@VLV~ceTj9B z<2_Vya+kh}SK!`WLM*}hhFE;=QJ1B@@9yw;aAy25=_Kh2Gj|_Fd3^6oMD@a?cOXk$mQ>7}TPo_mV2yFr1B;+v2CEkmRfj57AuU zsw7o6xV>H9PF3)JgNj#vYwKoj&~@Yfe`A?)Bo>M=nVc2lgl{??Of;2(9!m&dZhjxx zv+h}+h&{y!;r2UtxTLNFP>ApqtH9hdl3))BLG1Ax3&B$@51KgPOQ8ri1US;#!Dd+q z4icPOSo!s9_38L&V`Q=IFH!!c8=@=w!^ug4*fSNDT;VqYkZZG1!bCto&t)x2tTVPR=?VX4l=jW@@T%Wyuvqx zci!IKAA_IQUEX=?yfrm8{_--zjPJ{+PgCu8NVV7j!6PSnccrG4P8&~vmAHl4-lz>GGNPqL$tf{G4$0fVtku>*MG;hzeOQp-AoFZm=#>AIDE(UFI%k>emu`q4`wh zn4cJb^>gS7T{A8F+MkO>tu*Z^a!k3D5M@{sGZl;Pf~2Xs5`X{snI!b9-rN>BPoAcf z3$J|lEw|34v|&rqhrOKx@>V(%*H2X;Xk?eo)?Q}XQ<@B0k?PXC$o|BI_-48&hHuwh zEkK@wwji82XxB~A|4p0k(Q@}}zKjX%BpV1(pPHpa`pInL-f+F${a3K_a>bIlA!()2dVa-r|n|JQ+ znqNBV>ROxYi(A0l6)Ji2nyhmg2-9+Css&zT7@%Z+9tvtGOq9*^@$w=>aR^Wt@4bcP zBu)u_@}G{lh=F`kEmpUIZ}U=}btB9>1FklAG{pyy*xUfxuan>RCf2gBb=i^=7fw%4 zBX|Sc+#KG%RiVI{8vi@F8bRv6uIHxw-ZuHg<0_Me*_ZHzvJ6KgJ~CR(L-E}dDMz55 zg5B~3kMj=tx}U>mWvbE5NxPEpZ)FxNxkxWXpUeUvBF=S(>O}KjsL{^h47&Rw_YZ-g znkK%{>N?xIoDtO&4cxng-s&luoT&XlwDxtyRU1?dHvyF2HPq;g1JYz@b@r1s6I1Lr zqq%a8#0Bbg)IyY##3W>%MiE?f#6}F)X$pzhJ+tU%`tzgWweN=bZ(K?3JcS6LR|d&o zo7xX+%*BJ|NzKIG5vx*I|H5|=QS0x#o+=6`%U_}CHO zeJqzZtViB&7OjtJ!uFRgIQKDTz0K6pN_CVL+l>kyY0od!_=BBerAzn6HBU$%xOxg) z#1foiQ00^phN~X2XI!j>Ybbux2h~F_@)g7t9BH0hP!2X^7D;&GCUrL!&l8VMCJgE} z_^;*SB!%;|TrD0~bx!`fhumveBLFqnK`ij#Pk%pjr}b=;kz z79xdU+0*pY4;ciR+gn=VUJ|7(&ogAI~n4G`99vs917Z;i$+IKaK zobOcz%4YBHC4{E6)EmMo&leZP<0XEXPs7x+y5ZYhD221ZVj?0XVD=C96_L6H$eqaU zAODiZpN4L`Jz-c{uEm3`$pMKBmwJ_hq-C~$&H)F?SFGdEpD5&>y< zUkHCz@n~TgX!AVcSXTJ{4&V(nK?V2JMcZ>KDb#Y&`}OFm-#NOkbJlQD1e7|*x$zKG z0sOe4x2$BM`~BW6IefTMmLSL4kWpJ~pR);;4e1>Kp=0n6A1Z;1^00pX|f)4CE1MQh)8 zWq`c_+4?L}7m}=$3~OO2XN?EJ{^=O(mfVNC4^jHrgZc6-G?;MT zl>ON(Iqz=4Tr3mYk}IvCQtMBX(~&;&sQ%WxEckbGIHs}vfrrKc&6={ATFPFUv3=#E zER7B=5wq9NHFcLq_l1*_YVCtRn3+;7H%NfZ$!<|$QYEf^3^0aHVpaR3-ZqcD{!N;8 z?I<0BWKP#K{+GRPy5u5owUA?W3)!NaKHS@@$QS`~lMMSlv8LnFgj!&&ulrjzdzkMH zkYH_PD{7_bBYpSu9q^vgUuH)O$@lH}Z~BRT{;A=A^1N7}6s<>X%kodz)ks4)5-k{c zr=WUoFn~m-VGhjVg&;D_k$DZMKX<+%=o1;}y_Apb&IfdOnDuC7fcgNi>_0x$q*XKX zh8;b6#ctrm*vHMxy%f`f^MlQE(!0Gc(sQ;3hQEGg{Q6~h-`e8y{B*nR@w{F`vQZS( z-ssSP^s1WkkjE+8mjFTfVqcTWogLBiogAGyIR@taRkAtYmFes}VPJc9su2|C|LYV?rF*D`A1v)X|;Av0#;wu}VrSrU3}q zR=>{7%-g-}Ec{NHJ6uav^zYxl*QuAc8=FU=IXDK;zWLK&2R1r>pyWF15XgFE8wYH@3mE7q#Zt^eh9zs*CXv+|;7WGJY`_Df zwMC;7my1x#EE$AbFf8hKl$WdmJE1Q1j{6id+&2G3!XaM%%a4nH-6*n^WJx-V7y0eu zi1EksWYPr=<@*SRPHv{KBSh7|d>t{H$g|@yrZrRMsLV47`!Zx-L#-g#+gZ@gN`n$g zeT{hl94sw5VK!mOsENh2ml=U0d0*YbPoz)2%y_R!~ z5{fbFNsn^ZAV`08`4mz`d=N$>@b7$uFE|!7h!?HqA5=RUwLjw5gT)`!#u$;ADVpXm z8K&9-6uT|JtGm8uMWgLS<%(&K9r4~Eb7KzHW3^|wsTD3OCcT!hCN`B~QHY>np);?a z+0pppE2R(#!#0TR@TUTd_%0HWP{Uc``#RUeJ~*-2s%(TSitdC?JlmXry0V)aon()r zZ&uY&mK}J-B9fyfZSdg@pIq0xVRSS$Gy*QikI%B54ZkWyL@HQt#9xlQY>3{B0VALd z6?#YcyE%9f*pAfxrF4-m@FuJ0tbDm+;-TZO(wb(^mI|F!J3UmmsPev~u`5)CNuPo` zr|IV{&St3vp|6g^`68 zm9T>`*=JJNISsJkoV-p#^5FbGJ-*L5VpYll$myNvdU*KvAC^<40KFP&--PP7q{L=V zgrcBl+sx=MEJ(5@QkQk7h8dfhhgv(VR0WtwVn8Nv;O2+NFFRz93sd8Uuo;lD(YC6u z8+3VSkF66J6cq6A)Q7#RwJ7_29l=t4k200Ut|Yy@y13|fxt~%sQIy-j^2WH&#?#5k zDbOa+MmT-JKdW9x6xrPC`Qe`)AVC8ukrFf7C8-iNyxrTS18HgLOz`mWIXOEmwmD`a zZ>{fxXQW0%n>+GSE5UKIz1E|m*dga*7guw0BK~2?7tu2_MD*GdZ?MOGFr}-BUd!as zO=`(gds13DFlqI>*Kqn1zN4=PbM6EjSUJqhkkNh2JDojRc9|1@Zb@NP6_;@)(n90qM6Y)3u)HA608*c~C#rFYageS)Z*I zGfM=o625z|tL3`CWq?}?%CLogr=`npx|lGdPOmGc^|cyF_}u#@9n2*95^m)<4)nk% zpUD^5e_u~^r?7&tj?RIqK9;GbHb}7uG``mM=OFW;#7=d|DG(^+CHrebU*P+iN*7&q zUH==M0hURBt*|~fiiTo}mNf0o9jqVCYQjavA5i2uJgDtINwM%l7Xt>l?*33@#xD3u zaTBl`F^>c0#-|Z%?^T|Mzmh5gn8oQ)UCYQ92EHn{W8`^BY5$O58DDqQAb!Mvfi86v zq{!k;{yLjC8iZnF62@sf@+Qpb^;qD~vbECo-Y-#toMmYmGE^zE^r2%e7mTmyuoSI9 z8Z|X{mo6#MWqfvW_#vaT$dd?!B8j)gJ<1LJs*Ix|s=Sh>QHsSYc+eYrdO{qvRHvp!kBI&hq+3Osl9|sc|7|zN8($!Rv zDgp~F8753YG-U@`cdmlK0_qkOuJWsKgi&DRmm*C3#*zGw;49E4qG>APQ@ zSt$_bLE>vaDP`YbG)mXP(#6L>B8$fVozUgytm~m}=pg(FSKvxq^lIgu4ZJlH^H^6Ml~)+_7QEr%=f_9?p%u|-7xQm3St6S&pa=M;GI{_hrg#KHQh{mGTg z`NVe^qUs1qQUmUq;Ibf79_bo~B>;bQeY*){v;Fhs^{wjX zM5$WYPI~%Lf3@Rh^QEz*e5u+bwIAO1^_#|(#jx`?S1d4NbF22d%gZs3LNHM&oK6OY zrjyn9T!gaLOu3`D$!DBqrMKH zks!uqvcPG^@_9F@nZ3a)ioQ3LoIi}o{McIDzfh>%rb7(=7OHC^!hCNsz(VUHPa3l5 zcx5SEFH(CoRQmPCQKW{EV4|j%4bmvcP-{FHjyg(WjUu*K@vd-`CI(~GJ|3;Su82^m zT;BU*!6>5`b|+111r{rlxhGqBNsmk3{IEvnI%O+i_E&p6xNHf}~R3C6t;;17s; zx;a>4#rJZC1idq?sQoq$L4Um`~_3wVDH*h5b{N}S98 z=lmNrXbjf+S1sEQ57H65N*V$o)5ItJ`I4}MKe`}&w^Rfc5JH`Ozz!Q7hW^GO+)5N8 zf{z0M7pS1e-&l}6ASjneAl(q;JD3*ENvZWIF@Y4c5@F3%iwLtma9$qumJLPV62T4# z;S^s;VaQAFGJ+*P9P#c&Q0G6t=f~(ITt!a~xGu7s2#lX?Js=&Msi7lddw}RGYQlc1 zVP}ME)Fauz6M0=~f53FYc1c&Ce$F)@r83c`#>Pf^C)p+6G_;buB^!T9+=^r$=jX-c zmHwMqbCnfo|GXT(@m$BZ5gLpBqS8`;$mcH^hPNmQ#&1B2d)Khs?CiWu-`COvELZD2 zzzA)~H;+15^}|rCzc%Fz-}&=`e(*cfg*)NaMglOWuCK?OWGyt|-Hx8C+`6J49Dh>1T} z2+jOOgaRng{{^A@M;_B4A^-VttFEGonAl_PV!5Z^IU)9pGftQ5hFbvM1qC`zSbP}ea#`a@w-Ob5tW}_>DE6r09A|hJxe$#L(U&)t7RxBuw zVE@G7$Y>^YGfjC;5N>5b-P>ohXn#lbcWi8}pcn}9uL*{K)mt}=R> z@{%Axg$DixgrG!?35);6kivr|km<&}`C;k4Y~+3HP!$RSOTk+yK{T!Dggi^)3UI(F zI;TqByqFolbe|dUs`Uj*bf43x{~pbEnQ#(H-$MXE;r4thiKTXu)LfJ+hA;<54~bm-*+IgqM>He<&(r*mAr_C zIENnjrQYp`<(uuw-(%(PCONZvMH(sWUPKi=`x@9#)+u&gPw6H$!FfF@Z|gNx-Hwf9O(l_qo0 z^2E!u=E?{r6iDZU52C`QY>=hf0E5ms&o_5;4M>z5j%@I?^~dM++bwp1vTt{L`3l_W z`aAzFy@zz^`-*M^$#n04$Wcor(rE|hcccL!)i-PH0S*7Q{|F}u=)}DL;Ex@Lm}|Id z04nE!CrDT#%iODfHrcp$F0CxDtc1Tfcn?VOBm6-J@192vU+3d~ic=Bqh~^U`5` zMJ(((7$}_p7DyOKLGGtN3yi6y0qQ1PtydBT|x5%jeh2!dC;+^7`?pUfza;eu6PL3#X7~4*b+i%&CZ!8qu=1*hhHCA zt^prNYxmSVhT1HZXN}F$WUr!=h}u#UBDXFL`c?nNn5P@lN`B{LW@>_ZK`kM?Q(7sq z`&?7D8Y<9aaq?N+aIjK!MNK(_>U(wkf4VZcxO-?Rvo63tGzl?RK~vo24AC>u3I(N0 zHBnGT7O5$1MfT4d-I5~;nYsCefWn@Dd%p@rv4M*;0YJvf(NDmriXz>fv`wL`+n{}% z(#^C2Lj8rB?E(@k!pK~Afdi@Og8AVLXUA9^f)x>#Ib0;MT~s*@y+EJ2*C8rADGk9m z$BVbysR3>1Lnyh;5r=cFgu%uqxlFTOoA92m0es>l`0}nEc+7qNl9~;)wPwu{u-q0p zYxJa<1-o2@oKQtc{swQ(Prt2DIg2p>>Pc_?2@_G*IQdi_+1_|zZC8i1nA#r68n0Q9X{6cT80vJr>>?hWzEN+B4hHXw8L(98f5io?-ntD#%Ge@M;^u z1<#WSZV7hrcsQFG>Ut)!f-*rPi#cO6B?z&u`0Bw&=K-h39TQBY?Fwr{hbfoP6Qab# z>+2hfqvMXH70iMI42TI|3R-&I^Rn#GS^rDFSb0|Y*$Z}^e0Zz>x1!O_;ykIv-@ng+ zh?2wF8vCT3opk*qX$zMht7C^b(r=IWlhYL0#r}TkLu5z@U+VdM?Wco+8<|sqT&6zi z0CGlcL?xZZ!Ahs}?%npVco$vqfeMR~9f?j;UDS42M9Xg{vCT_dm)Mx_x-tgY3=*gQ z9QRkif9Qd&`-oka62UWERH&{P;WDgj{kU}nNfOBIhq$#=wY++z4( zqtmy3jL8<18sc)5`r*ori+@en3d|H=M<3>`HQY$;qtKffh_q~HT8mUs?y*Tw`PtNIH=kHvErtk^Bz@U0S8h$8hNU7UD77wg5s<(u`o(kznTB2YR~(nZELQ_?vZMugAPfM53lFr}6dY zj65fC5}E0y%hkTEcdp@&(8T#s_5u=pk}q5^Fa>mCF9%XHi)btiiThQErolAJ__>dG| zn8ugl?}YHUyFFilbO;C)WQJ5lRZ2SPKr2Tm5Hcb-8e{>@EIpvx>jbQ zaB!tsOw{Yg*%X061A3ZT1G%b-W5!C$XUoKnsa2Ax9UHoRj~i{ZDo4HU*J6rM7^3NN z^Plv1)+l5)(aL}PdEEl)(Jut^rPXx_tf1a<o~wAnB15K}h7-;7`>xP|{LWeJIV7=ASRg{-AZxG6ZPOX}mpn*1Is zrx+l4D5dMSK!(EFHoRz5?tu^qynUiUApYDN}d(4J>jYorJ*eeE%3x7?w_t`+k zII|q4O&hTo<0UUHQ38o1Q%#9<_%zHBG7NZlCkJvb#{@r;V(Nvb{4AMN6jbA`2NMg5 z4j5`W7AC}(w#P+cN#+EGGYJ%_sn5Xx{&?2xo(H*Kian0w(PF{SlH&LY^2r8_RQG`> zr9Jiihzle$pyLv?w`>qW*YlLS`AUYKFxY;hgz@YqC9P3Oy)2_rTctn4esYF}SJY1F zw1=EFo}l*Rtn$5*s|rVDccv_MPfRZtY4rFyr&canc-^u_8*Cw${aAsTTK-R3$5bLw zTV=u9Z-I8p-Z_tC8GoN#md*nlqy8kxX4KhpDwnU_2X+4c2VIxPKOIhZCl<(4D>L=s zLSYP=2=aW8`b7?!LI`wQn6**t{^(BI&Tk@zbaBD%c|#G%r630UTo6(Y3+qxa)6AbGy4S}w zSb1b`Sn(|Uw$`4HNqMqed^|i{d|(T++2Jc49W3tWju%%1CW?c3ZRQ7mgom^y=#HdT zR~KCYR}Yz`nk5VF+01Y$t-)?+>BMSVeY=#fq*zx?O?%xY0>bTMois4OI=_?+LrKkQ z_C5*H;P*cEz{4c|oWprmgs;NNy~E2MVUw8ZES~4klwi8z1;^YV{`$GUplHR_Gv$#; zGvsje*o`dK&2S~1+YmWJ>1W?6#*`=U{W2H+Fl|m!#}V2AK}Fq47@TrUml-7iT!yxx zwYCb?WtY)jc-e;)*dmltexkC4h22(Vm|!AGkV6^i>#QAnGi(@Il0yCKdh;jkpL!+^ z>7o4<=SZK($Jr5LH?gX$NWluA;vpkIl_&^aU;3WZ7^`cGdSw|z*w^w@<-%6z?h?s_ zy`RLxd`fLfd6fS~O`fnog2{~rC+@z_e5in)T7;C3iQr> z$$#pokHkJH(}WH>V0_KP5F^N7N19-ul0V};k~G)|p^xPM z>;nfGP`=}zsK1`^w>8DihiB9E`hTUC)f>o2S5l}u`yJQ3U|VVaeU(F>fkSMQCrMB% zcz_u#W9mUD@}(UI$O0A_(cH^%9EGbbp(1>W-ao7G%F4a}OYje?J@{EB_-pNnNZacR zNzA~Q8R8-K!?}cdg~q&UkYB)Gll%W3eyv9q)WTO2A&B4AM#=)7J#c>uzO-QQ6Hd$3^E<`W-vL4nBLFJX8qaJMbcqzB41hMcqClbCU&krtI~ zw{KT}PLGx;tIdx(R=q{9b{8)wIVRo(&wPd!^Fu&KKFxPq>^esl*Dl=j))VIioK(lAu+QXwij;;DOXCI6i*=P)d7`6Vy?5h%X!z$qX~$Y&x&1Baw+mN# z$_@ConzAbCd^l85g{1V{H}A{vu<@vfo~Y8FDnqAGO+pRy$gIiqMkjaWhg%54%81J} zx7L?d6PV=|pM1>eJS#$*y z#CWwb@6I4)kDj7Uw2c(q?feQ;8C2Tj%qK(SXCig#tBL&4Fo8>QwgbpgP`_wA>830< zA%Hj+I1Ue8|51Z6&!PE8s*i?N*gkP@UyoXr!w!Kx!0VRF)8KJhjfNqyu$LHxLNd1j z%aNWOc4Ub|*pd^PJc3Y*0%txEdk{qFH>P_}iwt0^i>9W(*5;R{lwpy~cel`|H_cZSKEMx?fJuLQ}IDJxKi$w8IK{ z`L^@evRteU&rN__KFw(W%6I$Oxf37c`BPTM@*tYe@}LxSpMnkP^3(^hmi%}}4tZ%A z7suIrmzvJ61i^rifBd;&p)5C#oDSZx|XyAA(Bb?j!qx9YFq4r z>7|1nSRg9WLHKWXU|fP6`A-=9CA8&3i#GoMrUrL+M-L7Z0OA&=Mn*;^I+hOaIZHHu zPVh?wymoqtN#!}=H*tS@EWOUgl8H_msvN3P@|+{L$UMON$$!0RB~{x`<^Hyre~)hF z3vo3DCluWADaEnjJ$a?edr?Y_PYI^%-qyx?VVZP4L98!Cv_;QyYzo~|_tlnVx{yoF3~{jA3jv23=s{X zm1kN|@!*joUg4&dzEaEO^k?2wt@#&{1mm*{?upU%50jW#iDs&Uaeut9l#8=-^UqER z!yKTLz%Fu|+q2}ch_w!&t#P+Ouqxh@seq_v=2*OZI11y8^%yGuEQ(0wjQfXCZ{46) z*5H24xaRY-tz2|>BoU?Fa*gXb-IhLPz+k#}V0DY>0 zxcJXPzKw%1VG32!hGAMy{+_6>thH1yW4o zFYn6r3tFwExLI=hEL7lVa1zTXGpb7`lmS2JNHPG5tOyWzU)GOPDAj#gP~61rTTe!sRWr8s*n6Tk>6Eb=smN# z{r%*xUF4V1SD@VVG|GJa%%(S-eC?5e#J@{+{v)aeLO`<;<_j~t~T8OH{pkK<8yFOS_D8G+8k4`=r}Ly zHSm2oY;n=34ZG%K5^r%rDPzgY^OHT1uHHBtap3V+0!siRLI`N-QLSM1O}c=1+t)X zS2K%zk|Qq+r@#;&tD*024QtW@hcrg-X}(>L_Tqrqmf`-Bphl9={ODY zqmSd<&0%M``gXJ%oY&yy2O zKR7!&bd=TD*gHP*Cmfj7&U#w-a3k%7I%gw>?p*n;iod!z=fZZ)#O(WCyr$7r$Dhp1 z*b$`?OL%zI@%W0@<;>68%6>XtA8oV~Tf18!cDmm_H#NlnvVW@o%Py*dW>1`v$x+&; zONX`*Y>yU9ieSLd#Zc``Tc)p%l^v%V#=^vetW{H9>czb8?MWx02Wz3eKFPQiP3A4R&q9<6ux*gOh zJq<4>>S!9W_GPb@$(^w}4o?iz8>H=QU`Z&+o3MEwaTjw>&y^uiM{{mU@>fSAT!6#b z*G__zB^&!**bjwKje&lPed$4TMHG-r)IlwR|490xFMTL#Syr$z2W7%WC!Bt_`MYrQNWgxS_(ly!7^)j1ZOb->_JsXAEyN1EvCN35jnP&EJ-zt-q=w(1SC&$tp=vrZ^D_F;jd_Q4hy* zH{dM&s|UdVfKwoCH${M=R%|j_(xwVI)Qd&4pC9-VL0hu8kvV;H{t3uQuH=fD3kteSnL=v9#{}3B8_&ng>}9QsYAfa1V=J_>Q1?oJc)HM)SfO;zNuGA1RJwVS%1&# z$z@ys{wsz27}e)mcq|8B%9ozb=;OzVO~^UClZ0HtGhj<-;?S2p{*JV!ZQ|qrqqfXD;Z(z zMYGypga>;uhD=JxW<3#?_)By{O$4t*EV=A(5!MIZJ<#p^cR!i+7SBvd+xt+&9`Z?&|hyw)GgW9&Fyu|MPiw zeUi@k(Z8*!>G^!_I6i~l?9~+&3LqFsUE7M)8DlER^QZL#gIO(ig!|^3T3Q;A8-u#6 zx?-ex?eJuJ`h0U59D;~M4%WyBHpjQ2?J|5ZR;hFx^1}SDSq`!Roj$f?-|PIIc)p{) zCBG)t6Tvb{(<~lL{^cg#PFh*Sw>kx?Dz{A=v1C;%o$28ub!G{^Xo!R6NLx8hp1jcU5TY-^f6_6 zW($iOjT(bVgoQUE0rN*F9WE8X#44B(qt|gb+j^H&B^Utr$axL?Mh502Y!DDGVWz#? z%%3G+XLl?sHO{k+DEJh}(OZ`c$4rT;A_`GlVNP%aXo&ROzdNa$7*NX2PsR0k@fnQO z&#x$mZ;+&m7cs;pbkxozzB;LA$q*pX>;8gdLjj3HE=~SeLw}IsqWqD$fWGzH@v1~( zmTSp?4|UP|13-v}i#{BLW<~(TG*=R`NU#Ddm@Kdh&x%?&d zkA*;9P@@V0*GEMr6VI1iG7>2_Sd-8rXd`;Y*LD_`iYE9B2;5vZoflxL?srm`W>;y~}!Ugg-DzFBhV zjAP8}wr5i4NQn2ZpZ{4ENb6yv?Fr@71W!0Hu zePFnaT%02VhHbM3ph)`zW8^)wdv@U@6wz+&00u(7U&LGOxDU)4G$kM-OZ||Wg*M!)A z3LmbB;}Bkf(rB#B*FvtdPHdl}cL?9_*&L~!Kd$u06Dzyw*%-Z^qvG)|tB#gqx6kK` zmQ1=jAJyz>z)yVqp>N%4=gF6WzX-OYzZkguO1Y|zhP z6@P!V*YYh66&6!s+l!X+(qhIUFJ5w_$QoB9niP-QN7krrYB`1~59uZ&n&_b4RNX7U|9z$W)TO5na*XZxBo zQc*yvaGx#ae_JUS+n1*+kR z!xsaDI_ZB7unD7lmLeNdAw&4f-A92j74@;{ z(^2eb-~rJA6xFrz)0xaRMNC|wXt?@o+KqDC$npd~ma&<^$Vy(YWSLTo^9z!eBJr`? zEQHEK8Y$Iv0FrZDuzZ*-%=s`SU7{2w-M5vW^$kAT!VK4~Q_ZA6HD(4HeM%Nbl*dUb zEE)z=p?ETK#eQfbZ80M_hxg#2{~D}<3;_wwCD7~q2% zhOw;{hN^JF|i1aoiWDcIe(oPB?}TWw|ACY++&6q5Su0-NZG3MjORIki3tAIR8XX=xxKl)wY{~G zEe?^3oU)s%>>GL+ie%tsahwkzj>p#WhOz_b<(L4ZAs zk-;>e2OE8{v8QJ%o#;(w6!+V<4u=M5+elG$3!ZJ$4dE1~Eg^j*n3Q2uK2Wh$S-}{7 z@uP-3?B|)c?RG28**C?;G!&@M4GKIt^^+1O>~>sI6)hVLQisk-!t+j-r~alQ`m;^r zk25b_5|iF^95e-Yy?JG{+BK#^uFr-$9icqY*uPQVQ`GBEw(iHIcVmcM(=JWcg$k0u zyCtH#-Z)i~YG4?D=R^@vYa1;#?G*Z|=rLm-MLMTSi$b^^ALHt{nlM=aHz7RZ%vqB$ z^iK^nE~jE7`)=3+bOKb^6Zj2_f`WnM$!v>lHEk)Z$h5fgQ=6jp9Ke?7VIy5_VCqVX%!M~{C-E-CBlxN z$5u}^WxGoE=$&O6-;{S}GTAY;bghXDK$F=_Hk>7Nae{Q4+0r>P-$)LwfLB<`5f=yx@BUv3Y}K`<1LhcA!>7KIG8j9*4Km&Wei#`L?e%5_HeBzfR;EueRY=eq3P^US;bp_p7A;X|# zm4i=S6f?tb*-o^Uoi_fuz-!=X-uw1H?&bgZN*)`Q=nKIXq*{+;cYAA(RgxL^37N>J z7^!eNIz+@^XKSUY`EEN%uY1;o1f>4tODSf71wW6x`~7pz^1wavu9X|^?EU?m6Xv&$ z4Dtvz)YP}v*8v7*RXE^Ybh0bHS)s`4Xp8nB_eoqhzzv~eoH|kEJ47!t-Qb;;3@rp> z=g}%lT^&Ex8gBo<5BbA;vU<`Qh>Xkr%noPCtsDCL7#M<3lMk-1t!-)SB$R5%B>%H4 zzku9_(+TXvA#8V+ukSK43@sNmpO6Co%^9x=<=8mez^q~zLeeN_c7LA$J0$j{{HqeW zj%>!_y63g#lpXmJ%kx*Gbdd%Qvqe8XGjP2xR0(ZK=Jph}hM$t|UM8240NdLR5x|V^ zN}T>d)Rv=5tQw^`J`2I8H<)=6LnsIR?!~0^^@fX=7kft>;nd0EbGLHKQP8Ie1RgO3 zOo!CStQiH5aV(r#>J!FCju`uR`E<;{+xXP>Rz* z0w9tS-)F$?ZoM6WZk3WQKNZpCAiYJb^V8mA6hC?(37va1!oGwtqE-i0vM#8`%t<;# zNA;F8AsXZ$ag_3>=2qS$(w;3b9$PvS@E5-U_A|+8JI9l9)umDi7xgsdXVQdnwBoyg z1uu>nfxPnQHsXqCUpf3V?aOE#2LWrJXoY7*S-fcIw!g$6JA2OqmCZb}US>$I0g5OX zC_$Tu!w)@1=j2kW62R&&$-=#OLm)(P4tOcGX|@19S0|kK*FK#e2tXFKzfE+&V-&`) zXeC5(<(mGg95c?)uBYs5ik;Y|KWLDY75F*|!Fe$8Pv_r2#lX%i667#Sc7GA8LooH4 z{EdO|M-~+KK-?Rf-w6SEm>-qb9#>{h7aA;h7SXc>zc!fq5@m{r>t2!NB z^K0TGQ5L&+oU(4D7Yr!v3MkR=YoG?8vUsn#bRtf4w*EDv#kI%GOf^Zd(V()&-sAmE zU@v7g`N%*|s*E)U?6TcZvuxt#;+Y)RrqciPhJ7?SCJ!gL`9~VPLQh$@Dm95LRI)ga zpI$ERo0^8^35n1LRvA*^f#FBeiMfP;uGZPVm1+#+YnoMTBL2<9i<*s+r!y#>v@>J3 z!0Muu@vvrRIsJihzi9R=4(9Pp*x2%=>_`**oNhO*2DCz;h?w^5CtZfIi1q1~vp@y`#CYr^#Kx&H2#& zpZyv>Xs2-8C~!h>cF0t}Qzuzd@a@6rkqNurpK57Z&`T>OB?waV0KNV@!yausg3^q9 zhs_wa^qmwl7Th|51HWJ+-zW~oM)b?yG>pVrMH!fTvR=QpDtpdn${8FQFLWEk$?g_4c= z!+7iUam5~Y>sXVqTTwUz(Biw@)3n=wOI(v&k`$Rb16)3`$^=p-iK<*H!y16qv7E%~ z{#EB_nd7-LJpN&wAODZ3w+xHA|DwG~>F#b}Kr4giaU}&VfB_u=| zq&uY>Jiq^Wu5(|{yq|ZoXYcRcYkgK~FBzth;=hA09{Vz*u{Q+bc#-cg;WzfTSh>#8 z!vx{zQ-lZI!%lJG>*Hxr9B~<+N!3;bkXJFHydYrnQGGGY&=Ur@1Jb$lYbUL+skh6R zzrJ1jvkJ035;bCBE+Bjqp&B|vDc;CcJIt7+MQ;qA6mD3LSr~zf>O>%9ca62V?}TF$ z{9PO8YS*ivp=@8yTkgY)F297xHDVb_6sgx#PK_!k87{aH^1!P4JEY_&&HQ>mcg4)l z`(!4HVJq(`kTb=%e5{wYizt1_v)G9awf`s`{YH3acG^=axG>Bt7ZrOx+Rmkb6tn$- zZ_pVs5tDEi6YPeR;)SW$O|Z`q3`59c?L|8K^wJt@El$7(>9B!MW@aJi6~;BiD-R{$ zrbW$_Q9^?e{u|BHtC)|jwYbCzvSP#03S*R_Nr&VL17gDf?OqWX{NfVBw-JgF7>ZJH zrL&62dYyG{LZag7rEL5t?R^&OxK|7yE*wk`MRp_=-Toyd1qwRQNr?tT1MlUKNV1LC zwb*A)TZsav!Enc>sbmnbn-9I&poo#)?>5DhB4&C-^yWw^pK3~1toZ3#ob&TN$e}Wd z4i96~zY?!Jfgs;3v@>%fjpjU4%CUKv&6&Z1h{PeZcI_My;RH}Oty~$c@BFvK*R%gD z&pBtYcMQ}h9r0O2DZ5!lCJad9)2zFcs-}6^H|d2C^US^fCyE1Q2ekc72$^HDV1Y0- z;Fh*Z@;{r-_#e^U*{v~$iZK%1?o%Xa9(tzV!{bC>$2N{!b=n5ZyBA0_xi``uSX@4r9UDKrA=J<{llWUo$7jd8P>=HNHE3U^FCzOwpp^4 zsyLS(uH0&5H@CHYYXqZadc-zuj*r=z7?`NVXg7Rp`1pTKKnNAmy|ed&;a(YDv@#>L z3Gv1k9-rWpU0NyHup?4ufX?@^Z8jo~1Q0Qciyc2L+_Dw?Le_W}m2}v`sNF7`x@x1C zC~AHrA6#pF{4p&5LslYw#FE5mE(v8IoM~zNbu!+dFw-X^p9{@I4p_`H9AZnK=SXZX z5*$?X{XtbYU+&G8-lAWl^H(S5+TVtbKIxw@V1{XoI$*N z2=`f>^x^!M>=JZIg)$#s<1iXOH_;LD-b3riA}8EF`l%d$Zr|domI;}7(c7WA5q-gm zId|gs%%pFNI|!+gMmIbhe@ZE5-Y^DdPhh4KhL)g@kvUoAqm)?vilTzgF6_c1@$(;r zCMg5LtyQJ_H}4|Pc5$iSO^Tzg;~rsDMq||K8TL^^V$R7DirY3PqR;5)x6Nnfzpd-v z7Zqts55Mw_T0rZZHGdb1ToA4gRnwN!)$GtgXeC(PHz|nz5{7g6vCK0%tNJS~5%SqX zG%kt?T~ERh!xeLXubOce}T<5 z%Nop42VxKZNbEx*=O~yY8K(0fZ?`m3=C#R$z9P9G)Ris}`+deC<%h-}$bqTx;*Dkh z%})KoNQ?T~Tz4P(`4C4!=uylkFF>88ov6YNGuga{@80`DE5*X>@uKtIAh^EMwxTgn zFE|g?{BK+%TM*h-3nsEb^J_Y)Xvl;dtZ1}D(cVA5Jhnu z;2vj-?slk82tL1PGiJ4s7fM(5Iil@_^lLXaCaTwSo2S!N$<}K}bf*d5>>SQ~nW)CP zJFRA>S^u&8*zSL?9S*5z%|I(pu^ZFU$?~>%ngJ zB`IXtNYMVkt^zzhMBC72YChqLaW^I|A+!0*_B;{rR!GpAioe=T`tkv_ksw`j^*ZXa z8c&f?kWoVREtHXui@RK*KfnpS9ots;9yfUesX|_uP`Ea~FtdLtnjqbf>hYDfr;p6} zqb1t)yw;|qJ;5R#pJG?C0ey8~ zQh#knDV;>_^6v8Y<>uA+S;QxT;{zNFZ;bFR3VFCB&t_dAOzTR%2zQE7k3~Mpg=%sT zdC{+Fi{}mKv(Y?kKOLgSBZXO3k>n_IqX?L{giv1F_t4j~QZT1x%2<_NcUaS$Kqze2 zXnlq%-+Qut6KZ4aoO&P`q@Cg7j#f*v51Q^~AQKT^6{J~$GPQN*QOT%B_RYKTE!pCW zB2=&*^61??QmjQa?II99XWj1n#o{^39D7tMoc-0DOjj8!1 z6V{sTP;RU2!jIyXDAY?MDRK#b#l+1rao#cws^(6G!BmPeJvb3Q=~Jj`ad}l%XL_*C zm2$2R?%X5wPXWvZx`_PRceOQb>9r!6%Myam#y@6J-lz&y2zzth^zlFovZcSKW#6y8 z<@9np2Nw8!vs$r|pFfWWu#TTF9&uu*+_lg?h{~zJ3kYR;D5iJ%uZY}^%_xW@rlzne zl{c?m?DO60I!njOxAd@Q80LIa6WZ5Qr9;h)g+<|%F*DN?Fq$EN&&pJ~g~V$bY4nN} zw?;<1R;2c|sauW4xtFFnAY_}m4^ibj32Atk^f}16?yHK>I%&U@_koO^LF_Z+^H4?8u%maK~%$t+GUya5!?X_FLOxWDeJ5&ch$KVX{YC-L>}le9+oa1Rnj&QefsK^ zH&WLQyoE}nb8kb43<&0AJ#F1Jan6#3HVoe%Cz-9igH_%pu z6qJ&~OS!y=IIehr(6P5Tnlb!19dR|`*)MWr_j!`g!=&avm-)rE4IU*TY7BVbvf5}I zZ5b4soBx{mM#?V-8U0)o1%faLBa%BPz9D%`?L~L2Dda5)Agx&zT~v*KD!`Jlk&L$% z5=Z7HkH=-bc9v0Pn+OQfQv2gQ7Z9u}c2rfE5m`hkJe=Znx2`1^4o_u~_C|^8p_9m6 znAHVY7NNDFx*^fFjKp!gTC0Bs8)mWVv{f2(qwO^nNZtA! zYwb2Y1T`ycucDuO6dHXNMSp8-L1ICu*Thr}IucCL zUe&K+o;Ln$J>lMjado9QGf>4kbm=xoj0BnMM5+OGOE|>VA@$Sbff_?E&+Q`nV|zZG zkL$#$Z^&Y>nAw2>$8jp2TK@TT8%r zR};$|sCE+Ow7ykI*FpL?obL3W$F0`xpET!9DX`2>{k-OV<@HlyYFE`l6C|NVVg-HX z=c)bXusfp-5a4iJx~F#Y^JQLzRs+Z~+jn9?JNYO;t`U0jvPs`;t~#ezzPW=(MM0*a z{$)h~o1^p4EW;Gg*&gCDo}v`~N(3EcaqZ@H_f%S<_W`#v!%PmIi_#t?;a&5i)0I0V zZaJ8awtmD<9Kqw8*X(@`Q*qx%-q9jT;l7Ds%K(0{qDh**rj}f8sP~EQSfR2OJ^$7v)YkJMX!; ztv=PLba;pbLK|OsA`5mOC^~=I-5X0-m)wJfxIPkl=?%jP341f+`wq80ag0YKT+S*+ z{04V?4`EXB)TRyR!Q0R}EtZIHqb$oM>gcuGI_iTlYG?$izLfm~(IFkp-~a;tdBYt9w3A zrf-fU<5>i1`{Zt68FAZDxD{Q(BO|K@Y7xQza7^M_M6qZpWa`B<*F|J^YFHc4tf5yI zuAw+5T(kMtI57H%h4RM6>wwFMJOrOV2hn#(`ABVhv5ml!g|RQyA+6y<4umiNi}9CU z%J0ZWs^~f4i||*FA^oz)e04j`I6rS4duwp62Sceok=Ee!0fZn9Y_|3lLo`kgjsF5P zo2Nyh0H%(5c>Z4=1?Ok5(_!X^5%W=JM`lrVd#s%VgB(7Ot1 z`l+wh%K~zZN|CU4^{ki7VwgvkO$?{7SQ~w3cVy~P0hck-di~D&x9+>5W{ZmTX?%Eu zS6lKwIS+ODN>x;rSGAFo~F`FHEbT%Kfy4w@#;1ZTkKMR^@a%JPNx zt6FfXsu7?;M#koe=!t z%KV4~8N46V!U?z}^=bl}Ica)lCyZK#kyKaDDl+Lavu-N_kie$tu3|d7{*6snKK{%R z`C)2efv=Yv2hI!US60KCBiRmNu*CeWQH4-g%U`eufcaYyK#8ge6ZY%san)EC%2e*| zNmIJne7SIM{kI075hho=766#u)p)tWN}@L$bmPz{?Bi5e3IFEh)d)z`3|OC-Dk(ug z{tjLf+a+K3_DE7p9VUS=_|!z4x7{#UR4NX2Nj$9M&SibHe+sN4juTwu$%5u&fq8RNNyg^s1yegQ#SsyQCIu;*d;~j(KRdMf%~oi(m*(P z;JxH?ib295JU8Abvq5Jt4jE*dPDZgO_Nd_$9ad47=4hCuLIB29oXj)>ZP4kFHt}`f zXjx)WhV~JpVnU%B`-j07md!6b*xT6gR0Upr_l@{XE9$;(erz-=+_(?w=OPf3eZ;_w zYSwrUAEG~Rj&V-RMG)BR10!DW$qY!Q2M*B9*>vx$gav{sA-JyNT{m}_4;{{}Z5(GjF*-YDd)`_3GJJ*yJ0|t~hE^r<(x%)K{>=`i_$^Lf*BH z2Vr-D0bFubF>R*Q2TR)ZeLUwyq+ggPb|>Ev%IHOQFNA1`NRNG;^-U<_GNpSL3C?~_ z_MEgM92f6IM#DJWHOI~myJuFV4wJt#IH$>ZDVITr=kNt+66jF{PtVWp6zR*+9}Mi; z1EiV7Y<&)UpG$Ol8%iwvya`6Gf(tFH-B33mE)-L=uCsJat<&hC_>DI*G4X{voS^T-juMIiGJ8ENT6ZEY0{ zQ(U5HAq>pdO?}*uDnFSdxoaQUY7hW0C$ImV;KonaF`&y%M?cM3{{)yJL(4PAc5Rwh z11<;5)wzi5Dljs~06R}6$m_}rG`{a5J|WSQ$uXX>2zdjo`Sd@(0O2a&ZahmA$y9#W zM^jZ31CoU-bh-iH^jJ$+1<)$}E`V}ejna^#F>Bemy1hz7Gh+G^{@WiUdh}lTl8LqH z-=4YazX@Pfso=T}z5iIIuU@*w{M9SKY3icpML>xQne)c(!|-d-ATwA@ZIq6-?gp} zRD%3pd(+B9eaU@`*ck$hrIpQ{+=SVzal;s1gOoGACHxqD-t?N(wBM`^fO0i?cbBiCcGaDrpH~=;`O{It~WW z_QZcx{50_Dxhl{$rY%u$d)R!K(kh%{Low~~y?X0F2&KHoAStl?T@Tm1Itc_>KXoh! zC;EHo-*QU!))f(-;lLqft4m4+ggp7ev1@{^-FnL6;G~kcrQGB)e~7X>{amusS6c4y zd9z{`5dMb1J<2i-#g+DJWZs8YRg>>v&R+ODX{5lf0c2ZW3J7jgD;g52 zvLCQv-l1=U`Hje)i0gX9@H*rBI!;l246BFXUYvv$3rPn&FcaY4CG8cY-4z{$ac3JM zedN2GHUJnPZ_H{pqsqq8E6@1IRm;0u)4$7A+pl}kCnSqN2rg%uGx}i zbSUKMmvQ;1uAT1X(+S&23mPh$$o zf|Pb0!ZRyCuf_qqdax{w)iS~_B6!&{(Pa&X@Wl&X3|Y=3TNWwCpx4UMqF&M!t-l=< zg4BZ(=fEe>>vR$(Y9ZNzu_~6R83wSsovXF>rt#VHL@NFmLQjhR%&ousTz?>I5J&Ii zRxS1IsElH=WA_LKqu3@l%*EYik^dcChYA#A<`yv`tmMa|vj4WW* z%?a=mVxG1MoH^x&AP8WPm4l75SU#7IrfS#I`QcwwiGRNg694}FcY3({Ee7YC)-B_V za)>gOjqje%_dCCTyOjX!YXK!Hiu&^z?ePE#N8hLGvlsss_+|f8cwBfeU4}Bm!OMBI zRC7a%O))OZOtD^TbhD+YtG&JXWJXUHKgG~cIng&mMGfWaca(BMBJkbc#C4??;#e5r zrWa!PSe`Kr6%|?ASrN=JgWXJB8p?Ur_wMUKLglI`+leT*%IdG{8JrJ6sygH|n{IDP z&z!ctsor0w%9Qa)_&JO273HIup!lGo@56H~ZF=xm`AR&M{ga;iI>Q{@ZvJumF(kb& z;nT#$w5tnm7~k}(saqVGtw!*W%<>G?<-=8vJf-lp;fJogEGpRH7rolNt67jaakj_Z z+3Ll`MSVS&NVq%tVxe=x>UG{=?2>(|HurPm=?%Fv>B%euEtOTQ?(AgbdklKAgaUVI z%T{>b_?HOba`N4zMkw{9aW)FJ2>OrUh5})8*_a>kVSyHn(&-q(g~3q}Z>e_k6_;Z~ zS6Vqc)iMP`RC!-o2*!aFX2b&PI0WyoIlMhtL4j!?AbSy?)8u_@ zHH&3JwIm9@h1QSYdZH%uvdi6{LPfL8loNCYrNcjqiv`R@s}vsn7$DY?0mhpI_&5>C zwyygBu77`F<3p*dgI^wB)c1U+!rQ+R9ki!^X$^s^@~sg^n8N zW21F0kA}k4lGEop?5M1mc$y+{dS}NPTc0TO!vI#U8H{ps&@~9T+=GhIlJqcC%Xk z+GYw}krS6+lrz;LxFNY9G{~VZwpHL1+*LjJFhRGF9Vu^`S>jVc;2q+%Ej_DaG{-S7 z%1*{flQkDR>vn=eLT3x^|3So3MUkJhd_hYmv~%$*`mscZtNdtFE2(sDs|bkpKJ_+N{h*Of0)mM_$;LK^p&Uew%1;stg z-#!0#Yqwvafdl^o3FN>2SX1M<5dkiMnXErlkuzD_AA*8Oe^dulWIlo}r#^q_4}gcp zMm%Vy1E=_+%rS1L%QJgsJK%2xNI#fEY5IU8b{UuRX0dPfDx(9%bsb=b#S5cEJ|aQV z7a{z+i#*UIcH}mQa)Pkman6w)a8MumxtdYyeYZ~OW6`~{_tC@a{_&=JD!n}I<$t$! zy$*k1o|OrojnrF5j8_&ePftg_J7{~gpN2A!1lo8x2U$!*tE#HlYpdS1$GCcXyDT^R z*?PMKQQzE4mIB}~8}V*`7~^_1FnYTfd`N&-T1w3hhMb*rcsn!7skAAgNon^8UWM$R z(T{tQaL_Y8lOV;5M2;yhGN?b7In838&Ma{zgqYY`9HON>a}pxt@klgVjRkpc!S{1g z?ul>Uxe@teYr}(PODFeYIdH2nloZkuIIU^uLMbkmdo6D@?0Q)+WuhOO92b6QlP;9M z$AKc|&^03fkcUy*UX3pPp>_;B6Ox=oTJnRE^_7*j=qq#=+CMqRwCX5QFQ(kju?6Q6d^9b7iE_i2gRLpx$DPtbM8>w}p$zt)RtZ$q0&fRCE z)6-g&4m#exY-=Yw%32T;S?PCf`s|iCP2Y}u$+^XC>_^&LL;0o`DJLrKGI&3Yb!B?@5N0=ynXK7y1;k{`16=$tO~tab2V6}EeHLtP zleh7ZH%Qv{*S5RPyz4EJ8S(vAU1E8Z1U6}`GQMDg{wI8@xuh)jrV%6Ru?5)vNCpIb z9ZaZpArga*UiFcOW>S^3l=ZC`f^R4bs`dlA!Iu;oWI<~MNT!>x1;f4`abZpr68`!q zb0=rfRz~}Xtz;_egZW1fR!gkkDQnnlX0D4`PxNhB_~f3_`HbxgOjt2`_)UI9{0()R zqT(3$inZ!DqA!TMP%?0-@-+`W{2@O2PevPUQ5{X|L*znmQ^Zv1C;cz}Sg`Kl_u9R4 zBaR5^YKK}7v^J`amanckrf{->53_-tvjpjsY}&MvhwLsJgeMz0^mz!5N9m-z+J7oa zF7*C%j_;N~V7Kaj2-{3s&_240&SVMLI@(OpN!MqU>uxQ%>go&}vKjME4FoTe99&*r zUhMhbM*J*#$Oe_vFMKl^oa% z2kJ+tdT}P!(F0uH*WrO>jE1qHL>}FzVBAup@w8yryCr6}@lS2pmaI6?jXeqs0W*|L za^}pegSyN2)m6YuiNy+SCdeE^zxv;6^ZeAm>C&bMmS`~R`!?C*FLlazG8gg?L|WT* z#dj|+^ws;{1pNQ7DmZI?lMwF5(hZmZDEtUG-y3qibot&s`+Dp+xCOY@y1TUYGu2W$ED&(C=qUKU#XW z)&*>m=1>1H2t5HXqBG>n8sjc>0vc6k5aqj+;i--{pe{m?21x4C=BFL=*oXlKXR|A*U`jLW47nGiL?cMrL35^g0VKj=7t?b41 z8!{h3EMVPh71xN9F5%&Jb9;+llj7ud6V1g|gU?7!$5I(RP$Q5p2R-;}9j;P*r>cwP%Ci4fUQYG=MS!9^0qcW{Z2Qvc%rO^Q9!?$4tEOcx zFxfXCn@oBrhYg@gI{^BMhdC=c;DuFV1=g@d>8{Qn z9j%VF0CaUPAt5-VWch9PNgsDWazFx#@<}}-5Hvq1Pu02X-__C515Ci@BX4`|darl` z*BhoUi+mJC|9=@=a*Y3!B1-#a_KtF4-3=1jMS zj0m-q0cpBQAbzpb6zJaG`4n(l^uMc)J6rAYznjdJEp=J>S9Sbn=ELXe)$YKjy@`6@ z$*YxgCjGVF^VOJm(lhT+oquRx>SCmqFm}NPp@J4t6EFPp9Roc`w%9*>8Yf9w3T=Sf z4Us)^I?aSdh7zw)LF|z9*55psyq}%)j9Y4fqlf$3nC=3e5qCsLwM~}TY?P-jQ7@rP zIb5-m);V<%HWjiWX;0XIwN7n!XEkzGr-cg+{pL zr+uw+X#0xLxrLe$i(1N6wj(_5RbZpx9v&OV*+29n6um;QP~hmIKHtlya`}xsox7&- zryIf;+-hyYdfv-IC0Py9hm;Ta8d6kJ;!6~T2Vz^($A{;~AR&wOTW?3f>@2OT1l(Ym zpo*|GP`$;%Ibmh2Lv$|8Gw!6GK8x-2<3vquY)2hFv0NxZl|+Z(Le5Xdw-vHW+}tev zDENqCUwxpdUuITS)|lU13BOh!xlxHvWoIdA4~$4xd9eG=_7jt z+U-1Sr&xgyxI$FNEwA)gka5t3e01{B+={xRG1Ex< zNPZiV$4%-3;isyS<)Hd+{HyG585kG{U~hk#=x>}-9IbWv<7l7sz8u5QN15IjF6*T` zf3Kcv>Aw2UGNiHi+EoOz9GT6qghoT#m7s#R_H57{>ZU-H*M+Z_S2>l9IYxNKn*`A)lc7)9n;6${MXC5@&pcey{}q6gdH$>HHR!zw=b5 z#>Xe7rY1{s%D+YPnyI^Ve@UO4dx(&0eRv-2H`Wbw9V52Xz~Ar_6cZ8>5*JVIon7_+ zbmmhAFJBt;Q!`zyZP(nv({tAE^>UZZpt`*=F$ELN=O|~L=9S!Dz31)e1P5&r=;biO zEC}o4x`r0(U#HfG6G1Y}7UaL*E@bQ|1wT0F!NXYd61bTS-71@g6q|%mkSS50HY#&} z^5PPm>EHj=E7K;K%;AL0YC)(6FeDEU7Z4dA)bp_ z1X#~#y<&!8|6=_`jdY6;E%j{m;f)`@3azWXT&}oeW<|Mz;9As};?-~W?{{+asa+TY z@R&;uS}EBCr!vk1)f&I*$EE+#8AhUXd0|t`VMHdAqnIs%+(hl|g-o5I-A}&Ynpt2e zy$QBFmumh(grnSF84P*HfLg{V$6)-;(0XX*DRNpY%7YP+RrYX#WOZOKi2(%DB=5Zl zG70#APNS~$14BnLfWZJO(ISCYLw1rgY6p@AI@)9*3P)llk?7+1Zb`Ud{#VnvH2-JQ zkP1=a@xJdcQP^w6F6`!;*_=PA@5ZyHjZ2CA4x?HO+);+5w`j3{e{-bR-2SBm(LUjU zvYh9;SkwxO-O9-LBm$vq`WXk)?{YQL2PN$sHjYTxxA@(e(^2R=l@@3v8R%3)A1N1j zvDb(g&OgEmx7d%9A7k!ine?8cD>mk{X8&&ci{P0tiCUT%fXhl^yN0vl40*?mf42Co z(T&7RB>Y$^AJO)E6I2;Mgh2<{NB;U7l&9P2x1nS5PSS|OK+#ng1P>LJCp9L51%0lr9oBHP_5r5>aVb)w@g-cNZ`j} z7B5Y|rG4cTz2m67`0$TL30e*%&Ky!4ti;k=z1C8mhcJorBJOOTLaKZ!1MCNVoEE0YESev>GvcM3up=iFaYY& zzU(j=J=HG1#w#Bnqv2@tdIwN`Zxd{2gQ?T_tP)jafXbR4DEswZyOwU?b(S`pHdk>Eeba*u8+Fcb~l5m!4OH@nP5Rvyb=Dh>?MZ)8C( zXs`?BLuKf{xMcgy1vkum=NtA`4xA+PH(f~5T~h2e;2M(-@0p*3%em(xBhhM&JyvVy zQ-9igk61yLr=Hj>fqP0SGfJhecj*#-8H5&N6 z%*A+CS7FS3K|IvB-K#gH#M#x%{NWtQDBm$@6mq}RvG6l61ok>6x0ED_p}6?Km^+;!(6gLvth z8K6Y%CK-*A_l0r63WAf>v6^MQW1fvQ^r=~-h#d(5PmJ58E$86SfUh3GSx=X=rr`pq zUPSf%V#)bcRvL>A=jmFR2wBqrOm87p#!#B#XgAt`Fb_B0F6tb&C`u)<9D#1|H(}oO z?$1U0DHc5#s>rAWR@gBk}(GO=pOy`K4=dL29 zba-J@wHw5Px^5kmV$l=dg=h{{gR7|y+Raoir-PP}Jz|8U4Mw5Qw6gU`bh z@eo9p=`l^%3Ca5$#C18fVt!my~54)U=9@L z>_8L_6nd`spf%F~IuGDWKT<(P5yJ~y>zf_i*?Dn4MsfscIe2gvYZKscrYn`0A9Mtw zZ0_G@m(SiD&;Qk{G40AZjbjVuk5Myez0YQg`(DK<{((vK?x%@ouFh9W!t|d0CXykF zsb?QyMHOgb?4V(O3YJzM^fzvAR2Sc!_fow<*yb!Vg6iBQ8ePm6LE+vnpDsJFu<6Ap z*!kyg8ocD$+gFd*yv;vNWqVzPq2N@_RJqp3GQ)k4`d~xALGN{hTFLL$JWc{Z8smdiI9zCr)!0C5n79$eO4K3x!a-XZ(VptX{H>R(Q5-qsSKLR zf{Rl+IAvQ1pmRq>IetrANl|SQOQqM;@03n&y$P<(6%XiBLv9P`f4|$66P6yHMDPix zB9cImoLry~;tZx%RkhUl^oAuD)s^-|kSNBAUQn1$UYZh)^*~!unn>3qO%92BVuV-b zMB=~&T-1fyU4BU43LZ6(dM>6_8Qut(-1HSwjWd=(HWu47v_#NPoK+aWu5LTmNG*8m zFET>o%ed5VSo0gKSJ53HsAGmCr&SUuA`?W7KpU-M@@55;ZwMci*R>@z<^tw=vXH!! z-zEPbT!iG`FQfm05gg8z9Lm}#bV|_C(%1F3ja$VuCaq%+n(@|DG^1bPDBAZJJ|{>n zPrV;vy^#D(QI?hYbdSgAzmw_|vHi8pQXK~yp2bJW z>&ggYFPxO6#%7WpKrkErb(G&)#^FV#ZGu zO+B~B&Sn#Lspldp)TC5YO|IdtVn{6i&lo>7^V(&8bbLAW@9UJru=BA}o8u`hcxhD& zPgTcPh9wq;Es!r*&uhiX2nJ-{e|PiE(lTK=mgq&GP}o_-11eP179f9S1qt$qh-84E z+?;c|s$x*fqoGPM9aWfJMG{+j2#DkN2MstVc0vL+cA~aLckw$phrc(kYe9g<{ACXd zx^h(pu&M#5?q2Vn+@5dN1XR@jHNfhlW01wg=Joa9PS}&uDsRwK3#upU99d4lxjA~< zUU_Rv4#E^k#-HI9P7#5-a|=ILzlE-+XyIX_g6u3$SM$9?fCSKtQR=cr*^#`g<`1W8 zkhn77f|^W2P5HKv6}Jpi9&j7)*PXP{v->~i*p~)9a}`a_(BW^;-vU6o|PNSa~Hbv)H4gwbDa|3PM zUy+X}x@m|W;SzXbEY_V3CA8S0xO7xn^U^Ts^&)aoE}UWAF1)dckoV0I{={Non?2Zu zOD*P}xP0z(j69N`%^R>l15qY_;t{OVrtsWu!p$+)5pN9+;N?+p(|Tvo~sk%Q+2_U6AeB2k!{2SzUKqb;gS7-BMj- zA01q?xvQhMkFR!j+m~(cPvGHdYAW@x4yjD(1&)DzW@1SZXv9G|QiqAddW)Umf?-pL z?o8b)F!Y_hy}D>UncwO!wFZ8ZsXvKg$)7&(Y@ZRn*682MxZj80A8|2l5Krl+TYpJXKdGklQHcMiL!%a{4$;Qyvr(f>Qe=6t3$uXw4{ zkFo>Qa+Vh2YeBXy;yt6WPgOPM4(0_InaTr0GX@soDBwQexOu}i#81xS)xEK&!W(YR zY5-^vU^NjB%dx-(bd@5%Rf0=M{KDLlI|PQ(?@s*nYlg0_-u(OmKfge8a|<;f>>HQ( zOs6Y;S$-mf2!s^w!h>Oo>!1G#5P|_xnx7NoO_ru7PCF?3@^-ZYhX(iqK0P}HGBo>N z`~Q5pCWZ%hXyl0-8LijdGy=SCPGnA-m2{8BjZT$1`#)!+DfLr(M*9D=RGF>U^{D)e z(OhZ-+*>gss~s9cggL=3sH)DEmiUWfU-x3PmEL)MbaI+qN<&fgl~`}J5C~Bc6m^A{xoUKSTc2Nu1=LKNh~6Sb#s|;BTC3{as8#M0qOC`_7Av z&I92w8$+k;{rFYCv8MXl^t9}p%yeP8vf>!UMtQX;_lk3eQ)*#Js0dDejT>B;Y!cJr z9jjK%6Qts4zA-VF4cC0I9ibRf)sy=%UOCbor>^oaeOfSfaPimKip9wHDTmgV3I!)| z(n3l6u+vhmqycU0`bxY~?7BBBed~X8;1LKlzxer*=1TPS@gW9r#syM$S2}w3C!7(^KJdR-Oj8 z6OxHVIQ=%1e41VMpSs*Tb7j$^vjj$;DtT?(8=OvB@Kd->sio8={w^EoJFpPqAEXyj z$VbYf3fD7P!jEMIp#w$<0v9HIgbdjBpn5?fGUcWuJ$n|cTkK@2nYMZiH#dY_BH`*f zmMZ>vr096iqbNvS`J1%O+w_rbdV)%oSsWb}jPE%zbx z&hb%}8jPb?&#ZN@&|l@f#XjUg*v_De-!ZxRu&;XK^U_>%Ne(e%8Alcul`$PjSE*4} z{>Q)X*VfLVps}}4Mcr{mdcDR-g~Bp@>WU>lc3JvrR7}*>U|S}Z;=7w7lLI27e>CMCczd{*Lae`qS4KN8pp7amkp488;9b90o?8F`|et<@J z?0HqlNyAoSV}3LY2NoJ4yqW?qOs4=);ivTL!%ada2pMc((Jhh;R5{6!zS7mqYP5<~>pqRNScJYLV62d5oj0}L8*%G6y8 zu%k7tEy(T8!NID3_HOY@OFp1777x1IS-RTi&+d9Xd58m;*Um03Os%{kcjjZMQ_R|U zV!^O_qxtV8cm8*0K!&b(PF^#Xp{c>r;-c|K&ZeZJi}!$*!ECBJ0MJHoqm`P&U4IsX z%WU_*1C&MhG41YQiGwdLf5!9H>#(O5XXh#p@5b2lYL{O}Wx;tgH``0`lG5)`$a~+w zerP24X$HS4-1#)Kbu+!;lVzLNeC^V_X@o&?P2=Sm^q557$9z)^)6O1+f-^nmueYHyoP1Fr!9j#wPdi! z_0gZsOVX-B*WmndEsTGO+{j}oQ|BK!f{{w7X%d*Guhx|e*aOBuF#PDl+s@5bwH$Dl zmQzBpN)ehT6+g;8vOdcJ**s;I{PO#@oYdrR0}1p_n|J9!cKO!Cc)NJj*RnUZW*x*uMh}(8lTLWNB(YKi{R&P^7+DTY2{6QNYnivZnVE(*GJBrpu6y5I5TULLsmU63VKB z94+pgbhvco3I`A-gGZzl)N-znz_grn$+3;~G`-BHO2Yh+%Z>Jm%RuT!L|Ma9eR^nF zj+%{xw_bzDa}exh!jojL0Be_iJ}QQxj{KfbMA-Dk z4?Oxv#uw8yZ1HZV$RtIbev-)Qu=6(q0@1m&0{y>!L&Its8P*vtvU}{pYzpHP8`b3w znUoI53x*OUBJ>!PVrY=;;0#e!7@F&eZ%&e~2*z5?GQrk>5vNtI3r`FwC2Vf5yptGR zAb>KQiPX&^qL3`iIJ`IeJMW~@{45P@`-_`@p+;sv1V}2JLeXSm{MVhj)3Aa?s0kH8k5gEY*H6d zR&u;c;)78}Y3x`?QoIxS79D9BpZbtSZ38x@_1CT^x^pf26S^#egZ8ZM3SZK?~0g;#kkka}QP+c)IumC!VZn?x*^%qjT%ooXiXihc#D>pUb zG7eEp@`r_sBds{XxBPP2%V}U(l2RW@{<$Wd&u~cD-`_*56%NWL_(B%7gch?n6?+jH z&n`s|^?4c6FoVnkB{U-*(Zd%lf(Ek+Tn{n-tFzU=jP;#vGxsenUmz7SA+>jDWPN*0 zp&8%7c($cnd-u#XNzDDW`e-~(Qs0y&h_s0KL(I{!*kUk90)Ndj%kBo|9p6_EBm5`V zAzP+F0e>#xUteHS3)BOksj09UDR8d2vbN3gr;yX9DvnsFA{5sK-vt;$NjHdB1Mqpg z=q#ZuS;~(&@BTdl_|K15UMS#HAx=IXf&ATkL{(>}nzHAs+-e0OPN0rz>~_KYHlHOL z9j}8 z2wL~|NIGXtLsi_a#C$mU#JMae_`ES5cF@R{Zr8eep}f)cxxa3>1`LCD++d6wAfw(hx8Gc0`y0H=8*N z_7PVjT_%E^0}w6`m9#|i4BL3O65tdXo9o2CBD}IakEp2{veDN7^9ezm(k1M2kfr1j z$l;BLoh&XiwwOPMQaR+?(1b{_VKeH4UflUzQ)AaVSi6N(gye>*N$ty*65CNDi{=g( zVKP$S1*<|7zlDclTe8IJpMzo%S|^zYSR*!>^=09Wa?xvv6L<|xIJYWgN%7W3k~c=9 zF}C50)9^oTv2DvP5*=#|4#!NWoutch%`Q8>vzkv~IC|KQdf8X65oe=a#^r2t{!+&hRf z$BLFoI;MMUD7g;0fqv{@%IXWwhCthD+uoPSvifpg{_e?`1@%`FXip|848d6Z7SYaH z-!n5FclTx~mY;{e6vV4Pq)(c~b#e!_$ydLl5bw@Oks6x z{@KAx=z_^z^CIL5d~vuaZppI4_$(p=M1Ljc%(RvXvl&}lR}87phy^>~lo%z^*G&4G zyC6V@56GT=&NY8pQV2M%m;8V3$Mwz^h9cOM9rQH@)$=Ac0ASS17JO=dP=u1hf$6gV zPb4|^CN0z0 zFJpsY3TUdQjBG#yUF&k(SEe%rvRm>rq^A0(Bmx9Ih9JbY-94Y(eEttpZ`svm8?B21 z1&X^n6bcDmDDEyn1BDhX?(XhhTuX5X1lQv3?iANj+}%&!wa(f5{DF*oc{WIe{*J{RZ6dvt%x_-RZADamqVaC* z|4`Eep{6UqgR?ndlAYR<0*wJIOEq)D5ppt;2)rM8aruXl4Yxm?2)2lizqDe8Ean=V zb=7^3@ZiPq{c=@)6?Jb!a5IIRj;Qr6xZ*YSwQDVgo5X>0-zpbHA^dN%Gomh{1quDK z`3HC?9_l(Fb)sPs;DDcSiyx>WA!e7exO$k73erG$h4Yl3oh|d~KPc$s+(f}bQ)F%AppONbVQ3W3l?%V6#yH>^VORSf$0Vdmf^jB?v#H^ zHr$bmf6$;PQ#t-4ZDBR8 ziP!818nSO598G262vezVzOT^*xd~H*)?SYSpj@0k-Bs^13lFu)@b2b@_A*usP)e@# z_&SyUqEA8zqO2%x`R{`4Iu3o3#Q}!Afdt@8=) zlJ5)oBpGV&A}uu1=hFV%95|K;2p4H035fsvCg#(Ia{*4izxnIDM#%U@z(hk6RhjYn z=(tN_!)nlpzwMP-!RSLa-Cwn!s8JTt5OsHDp^y&AB zC=x_q)kiP+kAL6zpB37l+j@G>Y-?Np&_AU}=eh?#VG+D5<9DMf{prxL@%Q~2RG=a& zhpm5Lj(Jip7_?apD>Q<&*v`TVY_-3!{nysDq8tTfF)r0koJ>*Um&^%QGUWt|^tSHo zAVStV1kb&EWn$^bKTrQ(wNtS6N>~`EL7R`M|M&eB7v7EI)#tI*)v@Da z7$@=j73R>eb++4(Ck2zHT!JbD-OpO+t?+72ZI3qYo7(@bj?7MSjcd%PBW3+;+~Z*- zJXS>Sbbq?ds;SZWdf7Z$1bgrTXce&h4#KLDG#{UAA1qph87a(npwI=t_PGwn!UIPK zQVxO(t|QGBvQU!rXGiLF<-H+fq}M5OzbTf@&=%|>=56=`)GTZ)9heK6(MF7_ocWrn zsbYQ$!{1~OXMiZoAmjuTNPy89{PtJ;^qmN>QK`~XfP484?*)xe;k%F4ohn)SvV-$F zKD0lyhCTrWNt&V#pTN*2RM0Kv#d-^;PpExs@$v1r{mz?wu=d$DgT6Wfgf>x2VS>cW zn5Yml!XK@Gkx&1$`tN*{>*`NHP#f6P99550q zX73iQ#$mUM59)@edR3N-b;iKldtkqx9f_DKD--~4YrV_B4?~?r*0oqZLPpqEYIZ{> zH>F-ZPzD=#_{#WD_<$tU=!jvWdTQS%Tcf(k{sHrYnzE9h30|^wWWw28!SSf^6LsX z#3DLU1UXmN85l6?!%rG>M|xvP~ zRAq%uxb7h~3I=1@%!2C4$q7ZnQOCtOhf|BSw6hG1eNd4Cb=~*<3czTiup2f&>L6Q| z3&VW9wid3yg{&iemEFfX$5)&m@Qx9^oPm3-@_%-4GcJ=Gb&f0QC2O~)*7BIwZ`$i2 zVhKbWCd_Tm;-5RQiGNin?Bvnl8<l<5-xL8Rzc(Ta-9 z%y8gtW0?9A1wysz4cD(R_Rss$^TwM%3RkR#W8>*Qz-Z(Z6B!H>=bf#G z;(3d66DnNVwl_*2J8#w9Cd>p{*}mLl@|MBKMGsOcSfXgB_u1=-pu7D>JNf8g1C0+Ki&E$g`a>Fe9)BDD@;vR-awsi$$8P$r>rf<>b4{%u7ogyw>xJMea+j^2&kV zM=62UHg4M5hap;ddZu^e?y{6&-V}mC?0rgIst#2ROQr=ey$kgk-NsUJ7exqBz|SG{ zV+-9Q@p6WAN=*aEe`O;n7E!Xw0KgsbxR^5b12r)dZk$ZK>E)374|$3;4+NHmkAQmG ze?4J_IMaGb`Y~~X*H$4V^x^j3zYy0f3*vnrD*q^agj0tw8@J3zp9Cb?A~r%OLkv*uQq-ISY9tctziO(WzZEmlE73$BLW@;8*o2pn`O;(>#8@Doj zu$SW>Ru(|X$Y^xQ?%#4&YvO$YevkA&Pwz`(i*L^@HY{|MCbNoHC==$vh#a4*Jh6pz zJkDTF;b%ev-yS*=mEb`PJYa@&3EK`i2v+mB1|s;~+m*3wI4r8Z7yO{k;kq@m8=bbt zF3r(E(%w_0+ZtHvW9RpJ?xzY8_B`hk%C6|hHHtz8D;FV?`j~*ZGlPmA7M|`rYJYd& zf*`-wr6-+r_~wqi+llJcZ#`}fZ?5KvVMK%X^WTGB*|^j7PX80H5@@5-&EfWplO<|H z6St@+^^yh$FfJeJ%=v?TKQBLTAwVfFWTW50g9`9P*TyXsn_#nUBJhJi$1Ih&J|Q7^ zXtNG`Vr=ZM&Eb9I2iZ8PsBciYBEKN!&p!Q%#km%0ScGev@}P12bke#9-GKKTyS&vO zO!0i@l0C9u3d9ScS(Eq3luMoW_sY#@x_Du0t;NDK=62{gN7>UCpFCSvLFBsVoHr%} zpS};AMXf6}r4FnQ^HFX|Dn1K%d|r3W`3|9>b&?$jw-Yf$w{Q3`Vll{q90i4}36lN! zdry;*8P+b$t2p>+k$c6|63=cD>YaxWD6d`UQ`Eco#~^9!*fD8cPai`VeV3aY$y#K$ zS#kEX3F`v@d3uMlJ>hS7umpsA_p6>BK)iAcp0?2JmNSgO={T}7(!sEF2IXfh^)5sS zl5Loj*vfq%qFAVNe_Uu`iBi5u{>!y1F$08Ru_Io$rdP{Y}5)G?Hm9dx7REEG?{- zxQv)*mBHO>`4e=yo>5EL6M-_Ww?#HdNvS2$_qR0KsSDOQxdYrma{=*sty%zcGSMhG zTI{m^t#Z{FyrE05v zKl*tZ6zlKkX)~(hzO-~`*v4y;#=w;HoiYNedl(lrGe>}_1UATEuW9}S+|bFIdA4z% zBlwdH3!?sZB7MF?(6HvT7$2H~#N;y@ao(=zyC3yEJZSn^@Zc+6uthmEl(MGn{- z!-B-}r6<~SL?|HhfW^68Z;vz5*WBF9{;k?T)6r}WdqRQfQUCUME7xE^eR!!4hbUwE z@}hze1liDvDf98195%o@FrAQ9GjV#>5B&qKb1v+Kf98`D{eQZ1Z2(Vyi1@IIFU$7`eYq_6h#l@YuY#gI5))h7$d&-il36V*O|E6vFl^vrwyxDJ? zV zIicE;3Q-c-@K;CLH68lT>u0E*Q3K*cnBern@k6r5c~A-LA9w(7GKlaEUx!iB0!4E; z3|9}ZfJtn6y+2o+3zy-KzLy2I)ykz>%O&!#rTnvjcR6TMT#Fwx4`5(B^ z+0_qidtG|T#kF*AIZq648wsbQ7E4a4>^lwjIhB6pWsUHpKwO0Q4ntdMd|x#yTycvun%*u>U=>|BKPY;h&hpSl##6`%JM<;yy1>-CnqOutx7v~&v2yu zzez_Vmj>^Aouf#ycwa@`$lk2=H5x$v3Ld#|md1UE_}>wxKeolGMxlkv2Y}!&xlUf)vR;+z|HN%v14Pc#Xrlmr(J>X+8V|l>L%6{nIlgRKt zSmbE<+?$W6Erb9Bldi>Lz=J(`3{W9vZ5%m|Io?2+q4)@vo(SxoTlG{@N zxRrfNQRya#CnzDH&b!t}1b4nMvl#l@*>n`a*2~7<9T&$BhwV?;b{p;9PZMk5aa6rp zu-#O!k?vQE=h4E<tqo2i)JaE5TK5CweaLm12EweKknv0Ry8v@3ARvg zBv6cLC2KA1XZxlf9I@y&`ok-6 zK?-W-J#bOvJ>Ih@FofQrA@0airW_-mG}KWtcQGTL%s*m?X;wlc?ep_>VFYIh1C0O; zp%h#X1>4JJa=Oq}-P{b**URBLa)46_90_tI%%b|e!F?bocpvjTL+{iv#1TF!WCX>A zvCyIA7ivs2zqP7hu0IKFzCA9HEAywkY{gQNW-gLn@dVQ>e&&7VZ;6)s;y(`yvI}+9 z$QpG@*KpaEcymRE{Ym`rE_3hrc0aiyGScRY3dwdY#`G_dt}C~yVMkJYW?U3=!F6Yj zL6U*b;yJk4Zmux_C)uHIxDHeIyC&I5&ZS7vVvHm&@^U`!$(i~X>XuJF(tR6EJ&yE< z^v1ccQ~`BH_9TlOm_IO&M99rFO|*dig!+f5wIm)u+eRN|Q(Q#z;bPd$31sv35bA)L zhjOJfaW(js$_7=5f&(2Vt<|hLV&MUB3f_PtpO16L@jaCj6t?G}O>fiP=Ma>>Kh|j~9{ra8C@1XRi;E%fm#dzu=Zm zeo`~w6Ve%FovIsEOp!As0VXNC78)|0C7#PwZd7SRje_YHQvS|L=q{ajk^Gswt^ARu z_iJ$&VVA$-=~R&Dwjn8~{S_)1+%o^aH=Bt3lLg03qsbNKJ23T@f5(sUx$En$HyZ$fz4{Y5Fe zDX@h15%*RN5T^PAm9XdIasTL#3U_M1w=}+-@Nmdw_rtRFgz?q4Lq@RGF_-@V5ha+pN374PyMA*IEIAM#JH z1tYk8|2-1%^`{5BQy-RA;zlf}Cuio_C#UNXpm%_(p^Edu#7 z2BMt(d^3~~9FDcb@j_B{7k^lkI?WK~WS&=Rn2{D!{3Gu0gg~>oD*01!B8k$BnU(oW zE%}0D_P`R^RdBkj%s?oE`xASQo|U=~^jO6^8cT5&x;NHj5_-L6KA(N&Nc^E378c;{ zISxTpnVMZ0X&Zp_1pZm4tSTP_QAptzO)-;Mz=^}Wwl1ssVajv5Cs6}RJ8G;2?+h&j=^Oi;W$2|@2%+exmCyk~^{i+Y2 zASX9?^xBW1F?yQwgF#sPUu=@`;dH*DKMErlBC-t9 z?9w<-f8;d;nq9rXr?&|ClNuh5%)|5=ur0CibhV?*@Q{-boS8jRoDUU>!?pni0iIit z8s^@fvC+?wK3sQ|*#u&r!7i=3->`(OB(wp2QPtV8^B<@qLX*C=sti44Tuf>YY$;#|a zN^}_?>v?-NsTaUbb66;Y04zoBllIe^=6NFZj}S3JzOiWrpUC=WCdDlsSeWjn;Ze9AGFw-;gPmuOo$ z@NSx+Go%kL6G~8aG_YBr;mpU@talvGf|{^Z9X9jWN=kJQ)yMSCbXDacDyS-U(bKd< z0d-x90bj{6-cPi<$D_0mxXNL!`#dJ!K={(iR%lgAY> zH;aDzk9cHITJ@tC(7Fq(s`*v)7oX>)#XiT=8x((3KWsG*}SuV7-SxaV?@eQa#3 zM{OjvUWG!~i`xv8E#$Zz;=3N!B{LYtvaE}3b?#dM^#QG};8V4_ov~pSxt%S2MPM>9 zJ6Q&7Gs;|)v#97PHRZ=<6wdJ+F9VRx?HmdjV3JoJs~k8A1Yo2Sz~@7QWS?xrPe!5f zVjWxwkk^YKpTsQO`@lU7&`X`E1LcHZCr0hZ9R$@gg6-l!2fv;pfdkFa;fE`vQP3LNPvsd`u}loN$vhlkR$uo~f`%R>R5qE2H0QOj8Q#SzfYrm%nK5Lcj_wB29z5s`EeGE}>7+Xw>#7@* zki*;qQQacg9m0)S;UU4?ArVG4+3S7^x;ie zORwH`nQ5X;k)LZpT_v`po*fl z`zIay^0fwMO}~OW`z;He2!=5_Q}-i#N7yHsFjayVt1?@+tw@uL64<{`t(+jjZu)Tp+P|LYIYRUu*GaIW!AO;0j|7FE*rpu{aG`s5^AA{AYUJz4G&nCbJpYSl20!T zJp|Z7@ZPS@6gf1bAckBwS2USt0V^O(z}TQo2R?xk=JTZS_l_+?wAVd`^l!TQ-z0IolQwDb0zTMtjzd2rMUm%jHE-090+ zcN6*^unllNlh+#7NaO+Qu!J32l^aa}L*P&mf?bQlg;B0r8hdI8&=5Lms=Oh+UqF-F z;;=>MbbSm?9N~4ooC7e8Dpe3wgv%BWM>Dg9_1e(b93fOez|)<@ zvBS{|P1@rDBRS7|@P_ot6`smc#2^L_YZoz9tAdiooI=VZ@(ch}Y$+?FKXrmmh+sLA z9aJvd8+CE;X{_g6P0%l7RQIN3Yz%MjMG9s~CPq|u4&0#micOvgNdBgVB;_edw21dL9{WXiU zVLviiMh(I?rHpnv6AJAqxqD-!{KelhFCy|_zJ4;B5quISH{Iaw=8Dbe*#cI8kcr@U z{Q*`_%0cr)$V23_1V+ir()rH-jQX463v=caZ4A6d z!N#hnr}?G`Gg$ix&ev!V522_FvJwt%RMY~fLO%_q%DcB%9u-N|Fji!4i!-R{HKu8a z6nvtc7d&W(>tWERup9wSf?L~!5Mg8OFnTSC3bV=i;u{uMGXqV_A|&RcAW^B}uYc7D zOlbiarVz!W{e7R)qMt35@#djPeZB%2W#pfdbxjB34=Lvk0~5TXf=siVmO9Es=Wq({ z&0L1-By04(Wb-+0uQodqv+3T?aZ3E3J@kNL`ALpa?qgnIg|ZDbmQxV z=$%bR)Od0*)E=A(ZR0Q?1WlVA;yh3KS3KtA@VUVfAtv{BHdW^`vX$UkCO5@?g- z(XCPd^a%^H$=N_g0EXRAf2dWVGlsCcsX^@RT!(4$&dc`1byFo%?#%m*mf%1~$Don8 zw=C11muI8H=jQP>I9#hruhZ#fc_d|%jnKC!hzvNzs3p@a0gQ)+B2_~#JvrnI0Zhpx2N(H3uSH&46`HugJYG1Ey%C@eM^e_AOjefx9g z+W{G%QQ>~7?my8{LQcG>zy&?1vlGi5m{V^xg00*A4Aq))`&XD zT7TM9*r)8_xodLWAur^5`1c$X3AHF`DIMZD9&LVcFv4q@y2KGHIRYo;aCSJd5@ zk9OA~5it{cixd+{@-@{TW6z;aNHWFv{PYak1gQksMM3L3<=|NOkrrkmOsQ~{fthd~ zhT|tf$4xz}-r4}))itx+*C6G0fqCk%-V80*{x-Q9`P)$ZQ`;iGP{mTI(yZFAluDQ! z4~%(6qmExYw@-qbO;orEY`w#NCVuy0Rk6kBibNS=ZB6W4s4QGFE$+auJJ&n@*SEHl zc%t}NDu-4<)@B_umJOe7+F7&0#S^+vIwY}JU8lX%2c)XKs3SsOqHiDP&&3QU_Tk8TUr|8{`ZaI<&4%HD4iCQR(2*SdE5DyCXcT2;aso&xlL{SU(SA54Y;UBLr za%3-s!aB}YS4~;n=Q&ds2iFO6XV?Adf{c&X2d-8tNjGSdqVxD)WtpsR3$heCDyZNb zQ^o80%c+kMZPT)w#-9KGPe}U-h2w^}_Tl%H=%h5*i_Ko^GgxvlS(+nhIm`lr%&+<1 zNUB@}oxJq+_;j0D`I~VeaeRiM6CMZ<^-L&QdXR-e_uS0P$jHdNwN}*z%Ilu{>3WAZ zw&92{M1kY82HP&F&nX+Byao(|@bA1i^{r1rtFmeHecIkF+k^4L?S6GPY!Q&-wVNN~ zX;u27o|kj_|J4c^Y-syl%n*X7Z+$$MzD#v%;7IAkB%@9NA|U_v)GDwwMtDpe9fx@i zE_Xe3j6ObQd`Pi3}m*k0ZlF5s*7-4y$%-gr==Bipt4=DF+Nk>UMp zSikk^Gma1>=*n{#Vq?+SkFSd=%Y$SM=wkXED8ulo76i342NxA+@b{1Xwon@}2SYtcFpF8Zzh^HOB0NRm3v4;E?T_E3{4Qpx!EQC$>D^7(f3Gfe8J59CYqy9oRlAwhO*W)`P{KZo;hdP9yK9oTXf;zY z&|>!m8&{er%(<;)BFlqdlJ27NuOw$()rZ|hzG41`(o06<9!;EOWmGFpmgy?~F&PM@ zv$3N|SI4_IitJngwd#;d^Okl>+1g)t+UXuvtK%nu_&OQ=SJ|k|#RC zFYI}D{j!qb-E@zF2Bw-0%q}(CNn44_&{7p^!V%C;p1)j|u+!Hl@)iRCIjd{SM(xt| zML2+?_kQ%oktb-)BQ(K&#YW8StE#zkxQt~$t-laWZ~bD#j7a@ylU7vn^^+zi7D;vC z;hRi{Xb!fnOn0kUZdwuLBxoIeqnCsNk=v@3ewjAW_#XwC$;qB!wCybq^oEcACy8UPaO{G-i+` zj^8yzLq26feV>dzZE*ZYSiLX%kF-i3ci;XyjDPAcf};e3_nMcY#^-h)RMTOZM9lAC z6(_HI*r&pB>JJON;Q$D-6EyIIpDI)5%xFEkov3T>-@?KuEP_(R|8;wp*_#v@Y@HyL z2h0)ngh3HLH~lchMS;=b;YdoEA}&ac8%fJ~^MlGpD+WhHb(6&kC-o+bBCt$opXJlk-5>KG#1m zEW;v_o4$O^8{2EUw#M|y?GvFr-}pS# zuC82Uh^BNoiuZnb1}uQ~=GNMJ6S4@1^WJ6uSgzz9D5|^n!S}2zz13VNYFxa$B8u!O zm-V3+TQoNw|5UdCLM2HbmOqxA8B_TIgTB@1Zzj@E6Uuv^{YYYgg^(Ie(ecv*2wrIH z-&j{YE)Ia7?(B3hC5!3u%Ob94cd50yF8GsSPm{_{LhQ!r9!$r87IpEBaXyR_xTS{G z*fuQ|Leu%3B;sA_3lv`OPZ_m3HWwA4_3sIizVcQQ;3p=q(G-3th*8rH6hY{$bFXb6 z)N&Ge!$`w85PfkVW%W+k_h(oju%%?+b%dD@b2$;MlpuLbss5SzXFtpiC}uXl-BQskD8C1$=0TSm7av2E-O(`$`C;h z<_1;|fa(zvGnu4MlmxLtq{86!e%Gm9jmcT$X$Q1SoE)E5BiZAl2WJzol*wY`hjVC*UNhI`a2CVE@YBtOo!#<*1E>OglAQY)i|%*fivQ{+L8~BQV|b$ zBW=m2KI74H)Bm+@5hj3@5ZLH?YqR1?34p?0lN(=p3+w}LYO8f(fCsyu$#UFq1VG=% z6VHMJ00O^OV76)NtCKGdg8p|@`s)9M0N$8kb^(K+H?ZUb5x?iZ z-Mz92U)z12{|^7iY=oI!(o(hPQqUqSfdGTTYz;0WuC? zOm`m5&*e`4w>ULUq?kSRr(_Up@h8<$sDivd=YMKPX!dYSNw4UQ_B1d){$9#$gFAyopIH(oUk7o zgfwEJx9WD?_E_IobWZJHp*Uyp^C=jjmYI!RyNk}rG%6-L>N`WgVnRdby$-4vu!sn$ z4A{palPHR1ozystg#J`#A1KDGvdh?|HzERn#LR)}n^;A&>fYHk9FiWj(4J1Tq81>2JHf4Vc1NW?w8)~2YQrl(ZlsIg0w$f1%4)G5HC30WYzpA{S*p~;s=1{O z^UmLkgEl*Kl-2Z$8ozmjsVmKe{E-?eAx;`EE|Q{Ic;AUYBN_K;H|YdT)JD@qDQhl? z<0zxDMBbGQw$DYCx)hIojO6jt+`@9=v%V7+%`)g`Sn(U}_3C0%KK8mATMU7PKhXR-87oQ5H_GRc#PJh8349QzEptlZwg&mV8IKF#z*_S(%}vw{XLOM`3hOv)juf zrY0yQ^a0jQva;xN76sjS+w)fx(hP#moIkfmL%Oog&;G4c-2C_fLlvs@JHNtKxYq{a zi$%nWZ+gCu*QD!S_xl$qWm?|}VW{`--*OwlNM2vF*;{hnvtMgx+B*VF&I1)NF(%E; zC&$Nf7qVZx53dh4NnQ6jn5e}zs$^q-3AlRkxG2jP8IAYCSgS0wcK3hB(*=VP$T>fH zyMu4<`N=>_a!V0`3eu4pONJki`!!G<=+g1t%Ma-mCHKNPHBTlUorq^N1V-sJDr zCqZNIm;w1+sVyRmiEXfsW8B?h+_(CCK+Vz{qHjObz*dMDf(Jg$irv6OAWwSXfO-;Y|@^kWEr}-^eOWi2Q1~&{ZVs z!jj0CNI9clqI1>dze$pP#c`+hc~_tT()xrM8*NoTq=WLS%tRYETq2I8iA_qk(6PQp zzKAIF?~x~2Zzw{i>#|5jU;Vk1q9a%h0sS6X?V|TLCm4Rs!zN)0oq%WW;JA3}N zkpXE`Z5=3I=wi(ho zqtwU!UC?={X!rkRm68}$mKoyo0+xB}g*>N-p60s$?|eGB)#{q_HwzSrz=}E+h-17L zMFzjv+Cm`e94V$(42FlWNeZ>FvX_VW1z40Kf<+_8lkan=rM`Ed{ik6?fGDT@xB9_W zC75vi_~FVKW_2#wH6{Ajx*Ph?XLdMzH4g{zd-648y%BwTYK3vdum-$tGc>uP4{rnd>0UJgzc#UIC(_T%!w z?gL7}$HHt%FE|0_lSLMc&asS zkmzF#2iojV%h}hEeSu1uL8ZJ*&T+K!QcYYuiydCWYK{!(??Vqqneyh#5W7S33CTJu zp<0Vdonda9sQNGtcz>&E`3|*yVkJkq!=^jpAk`o0I!3A4)8q_{a0)zo?tLcpW*}AR z{isH?NecQ_RgxeP4ZlQMT;z&$ASuHF34$#w4{z?s+7A+x62axYT#JcYxK1&@ zEeLejV(E+zBH}2##PX7Q;LCaHDyO9PpUtcgzIdGC-SFS*>2q+rk9S6HJq%gdc2tPh zy+ouKb%?q6Jl~+@2cY49NMv_N;NpTg=Dd?sCRujD{e(uFb1T=M3 z%VA-ZWRh{@7Kfbhj|Ow%~&5sqfYLr$DQx(U#> zT{c^Sn5`B!Okvub5PI17+&GLs+Gz8=yIp&t%{+rivZ+M<9*=JxWe~w{3IyP{OAQ!LnsU}_ zZ;u4Bm3plI-O(NX^1$W+LSmSIlz{`=FD$^Ij4L14oAu!EKb0HW+PW>=u$rOJ=ptRK z(`V0DZ>n4M-(5wXGyt5^hkIOacQ?D!p3vw(qfjFsXB?%hPMmC=G-<`FcTW{s{`{(5 zqtrqkdHAp>SzNC$EkRv9Vb1Aj%?FZV zml+Ud7tTt&FV=SX3qj@!>JPMnbcYibP;UGf0Eq^epX*}6QlTCmuc`*e-ovFEaAp~u zglw;UrO$&88R*ZGljOlG9+M&_sN|lDVq?H5wOrOScvdNqrlsz6rU>$gw~YJ}ewY@! z;b0EQ1QxVZUP@3XQBs1eZCPv>B8k6M3esVlq#21pzetGvi4u{Pg5cQU!f%l`*##(K zXstl$#SHAD(|=g^J8t2)~1%@DD02$&MwG-Da)Fm83Hj4AwE3dva;i-(8)4HNkQGa zrWhvz=m6w|tkVXq0f`sDW#1|gv9aM=WaKqJr&%(O+v-X&HPxuf31fl|P_zH?6gAJ= z5?ddzhGjDnXk}6jrepJ+Vg+hwi+>tvf%`q2j*+V#tWN3cms&8JAdtR9cB@-7hMF5gmbBqDz$SUJy?1}Hvp12I89ko8Xd15< z`K`FYnn&}0*T*N(^;aGkc*lLiSoiR)ZG=LX52I^t%BJI@&&&!~G2Un`$Fo69n*JzI zlkphK1Ae--;xVYtpv#1bcHdQJEX#1i@~_0WQv#vR{%{Z?;;=xdAnbJx#=(T?4Zk~X zUK=gAK0Ew;%+(kHKNxbrk{!|g?b0 z)wvMlSenCCq@2GkAJ$r3F}W4$ci@z(F8-bH6aHR}(4vMzE=;R*SbUu2`E)*>s>Q4J752j2V~|~5#)vFT&SGKa!C6$VaXa1hv2l1jCJe5fp;;j?=INPJx~Ub z-AlZ;=cJ;spLkY4nXzy*3pS@g3aKSl0=Y7rda6ycFW7$&LwFOrUatC6b9-?%4c=mV#_WZ3a?w7aw4$ z6V(G!{anAQo%vzj{fg+@PYwiAoWkj(^*(m`X()sGub#E2sguK;s&LaRu94(#mXH*6 zrC9Hk&z4Ek`z+{>pHR9ME=LS}C!H8FjmYn;;?jj;o{m>diUoe<4N0C8y%rw7&nXIv zFBY75k3%1_h|x9J|Bt!%gA@gtGn3OSW$HO8KKUSK3=6-y&Z6FD&}pH(B-(e6OWS4< zAo}7(LgkzYT+i;3&R05Y^uA_|+#2J|`~>Tk!qRvRam=xs1x*>lSr#h`4lHvHuJ=gUM&i@Ny|vHPwX;(N@aaiNN(T~cAlaSp{n_og zMHAz6`;mIT-iSDSxz{wjY`^5!H-7}lA9)6H6?y96h8~Km+_7i>u5G0iGT$QhPDGJk zE5BsRw&Qa>kv<|KM=B{+{>A4AOUSvZ$rAQnVB3e` z0i=&CX}Dpg>2k;|W(NWKLd6gO=}wAAYbId--lEX<+xPT&TaLLhioogXE<>&>8g1z^d>9hrB{pb%%?qi^?ey( z9x-`8S=jZ=V$Zgs)x4!XfCCfNWh7%eefE&YK+@WI#`5nc=6QHZplH7&p>;4ldSDP##UL2Uwa@-aKc;TA}L zIe0&G=-fHXR?{xFC?}(GK1{r_(xaA;7a(LEW+$6a_@keY1>Mb9b|P zXWwmfvQL7oz)$5{FOdBeO2dSoh>O->WLLgTc3imj{ZPDT3`4g*gvz% ziA}S1<5pu}Q^8F?*;*yH$}c`nE@Q1|=VFzd-({03l%M~P1Jb}s@HNQduqptMpbt}> zf3@v6R{o+4gVh-eX@0&HBJZczbf|Of<^$lt^Z#Ru#DaX9o{P8XfP*MZ&%wM~MqHl- zGXtPAZ$2V0+PKF@1GMIUeLtO4%x+NC?t8bTH#FzWvl|z9(#)45nC?aWS>tRWpU=wJ zdGz&J7_VZeDrkJ}sG-5UtPDncwR*ig&RnAXRZlYtqAE$QI6ppKwINVidJHdPs0F}y z-)$dN?WG(E23tt)Z4MVPg6^7Ho?a%y>F?`Iu0wBHP>)xJ4h>_a#?|dR*sY*gQ9V@nKYX{()wWfI1XS=)EVm?_KjYZko8) z=#Qzv{>EP!AAdz*aD7HRmA&H-7-RMX>lPpe)YqM342DH7)m|aJ^UN|^l>MemoC)1T zd*K4=tMmE8C+;&BK(91EGz9iITLnf`i=8ZUGMIC>Y+tVqf9+NrfS_IEZO30sW^24y zMi+50NtamUK|7x%mSY|o12cNt)DP0b55 z@y;(R5gr?W$!>0%!kKqu#HyRU9qRwS7CO})GAKx%7Ffc5Ho8l}y@-zR)zn5IgBADx zA?huI;%b0xZ5#pwch|t+4#C}h&=B0+0zrejy9H+kcXx;2f#4841a}C|x8Hled(K}d z3TkRM-Mf3OXUWk{g{suXBmKkv64_qym@BPj!<0IQR#{bi??zd&oa04g}5YKULfezw&(u z&~}90!76JvJly>?IZ6xxVXM6FOSQVrB~G5o2m#&av$Ml18+N*0k5mf*TG~$cb5Ydm z{|an7rL?lv$hqtHs?S?L#kuG+!ScK_tit={RQ2+y18-G6%LL#eyyU#d*V^JRw)u7| zc6YDtQ-W-N1Mp8b|C6Z4J zZfm&C212Fta;5FtU)Ixrm~XPCS-j|H_nq^XZ1yBP3dRm=TAb68yW#cjb9G5<1wZ;U z9DC3Y2xB6e6j^QJOZEd=y-2H`V96D%{i@WwfTd(LArSIf^?ISa$D+GBQ_iu{}pIrjc-y%gKc4e{BZ0TA%98;jnGu zXvgNMuhE>_YU2r+JDnGki9ZD5RC6jU{wlOp43cpYk^r8I_{>%rN$p5>p7K=Gnx9$U zHKJ`$a#OKEJU{g-OcX(8;i3(dsa4J^x?NY)R7}#^5C^8U-wpl@Yv5?qEt1FbBO?6Z zA9WVGSNAPKC>LP8Ohr0hvr%TDzHs|uM%5OvsAh=>0T16Z5lcBHmRKHlM)^~Gp)xLH zf?pI;i`UO9lP*;$s|CDZe6rHkid2P#y#_AOMrrMrxlSgZ+j2P~;n_bAB9BG!cnRHt zjO0s(3aLLxJ)Md>ok+2x@Bc@atx^I`_?Q}xRPta zeJ&3C|AK0~O?!|5q+;KE3<@;3@}cve37E3T3HA0~w8Yyl$H0Kpc@v2b|3ZtUyOjbR zTGXip1HNOgxE*%rnOY!Z4>^5^`_J)V@cGjxJ-zS7dTm~|qJib|MdFZkI1ymIZ*zo0 zLCBVx<4CAyj$@)CxW5`!?{8&j zFM2j(E#zK~1IK#h)_A_j10Szw$VERaY1N0rMfVWhUVup+Z+|ZtE?6!jEa>AqIm>`P zDRB*ZmFSj8c@}cE4FsKh=|ic{*{9@8-S66Y7uH*eA`f&FGBifsxrJZGwot^aPnuDH zD=uInOgA!XZVCK%Kc5hW&{# zFnd{0a!jtfR{>LgoUSNVf>nfy?L@ zEu?~mY2xu*uh3a&E_bTE_MzFfsy^ATa6;lBR6@qiTuG}lIG?QnW&06QVw&kN7!)th;nI*EgK2@>5eklVU zEk1CsbWS-uX9j!8^}9?nzWi0?T*W>uTW*h|7%16 z_ZK782LDx#k$#r3UTTFOAx$zTScz6RrEdP(^>r#ygr2R7_H?Iw)mVz54GBlg-D|KouFJ z2gm2Y_gw4TdiW@0CV~XJ#msm{v5exA#UGI3j>@B&Ky?H7T&Y^!^C=9<_FpHm2(B4( z7GLi3{mB@^)zR?6bZ52hPi~H!w+95y6QGeHy3|>j|l$pv8CziT!geCB= zPY6D_4O5|qzGEX|D~~QdN8G{g6{nSc4R3Ymawym)L!=9v4Xq>+MbsHwuEvT(mdf;O z3e`*(I7F=YR4$FYW>d*e-bkAzBXFoaM?`q>P2?j!$(8;EJJ)@O?W^I^OC-;R1Z8lk zD^jo=wVk;(bu*-T*i9pk>56%F_->}xI>^YPXzKsP8Vx%1> zk)=la7tPa{uXzc&}J%#p+oec-5K0)omX^o$-=`5MSmHGekl% z^5ASvS1VH7KR5~KE3ea>j%^#Us|k{sX|kIL>K5wC`Rm)Znfcy|1@SEW?c3>QEiT1y z!tM28bsz^QjlkLG6aHLbucF3Jrn`~ypGgMy^x_mp2sRxBQ5Nv`CmkaFYKUal@El#S zI`aw_apCFDz7UD3IuEmdA5m$2*okTB-KC1<#w)-r>B?pFv-5(WQ>1?R8vcs=kK`mI zJ3T%K#&=ScpsTRYfSPba;wy;>K3HI+hero6sIOi zl(JpJ_$qxo5^w$U7=7$6{%F0$Qq<$-e~!hQ8?Uk)w{p!7uLzlnm1byJiZx2%7S}5M zRu#%UtD-sQF+o#WiORzcqPJO(6oBMQIm!mrC(pF`p#>hyfC5$I!*_sAYx3atX#omc zJb+}a_u0q@gmw*hetUf1oNT#o5BiH40D;BlO}|d!qhrJa1U}wGB_Lk7DeKAsuzW1? z^DhB1+N$c>YG;Q~>Ap?T=ewM4`+%ArzlZy=U)D3ax&ZR&W^e32h|GGI$Di>9;9_QR zE%EwA)Qr)1J20mYDw%Ec;}_ccyN&$`NEh4-x0deS$A!MJPo+by}^c`#^SHpBY zKcIKC3GA0?ihndOVWYG_ISsS09P5;aIxNerGqNd!eMEqsP=XVmveVqHUsV&72x4WG z=7VrCWz^ESm7}XG%l{U%1b0bd{1WV;5S8?`8?8zFs3N_4oNi%pFs?2s#S})c72c`G z|BFU07Vl;}ONEy3tgytCwH^64{!_NqDr&psq)E_I18R^BQ~XPEMM)LHN2T+AC9p9 z%hI5MNEM%ve7jxxQVd4ml$RKB%sMqR0-i{~y4Y{$lJR(ub@CJYQq_f{^oLE?! z7BM`JbvM&e9IA|=FL+1(nXM<+XtyX7^wl#Ze~S2_x`M~1!Xvq!>=NWM^S zR|)swO77z&^LVh45*O+Gav&4``Y~11QdfGxbrPfWd&kNVesYRlclHjSTL#1AEXCF( z@#fe|(igm^t1`Sr7P{?>Z&Ba;wbM5k5r&({$d5xuiBaukkfzPCF~1<}i?}xZ3itle z9-5#9e&9MQAcopV(F7%f3r@6iuc-y)Y<|_R-3` zD=BZa6f|FC;YLJuT3{;M(uTw&6zX=md zV}1L>)k5W{TAr{E+0XfyjM}_jFW2+e5c{Rt+RyDBZB4?xbpn)=Gk+mW#t(tHcn$Y# zGc)XLY%5nls?uGOcs@;X2bsEo{3d)Os?$*hTfSI;sg>uVAft~md0;c%1r7xKF^B0l zq(|;Wnn-!Y+?b3K5N{>w5zjF>>N#}vBoO*?2)CMIEIi^|UyI21l9-g)+-SiSMPCDv zrl@L6?Oy(z**cy>-fL-EZ7#0%x?Qg**M=zKy5F-ST?Ix9AK+V#+TUp}RTee_z|H6n zkG9(%N9@;`E0>P;IGTq0beOAtzy;Avac(O_{7Qq5Ex`)6FTHFLbsX9X zM$C#6X`OmLEX{XdKAEApy`3YH8{A7TE#koGKaNchC?;BP^CkW+xe~T*UrKTNJ9@?0 zAQi`PW|dZ%)Pw(Ahsjg(UHXdxu@n-01su+|@7o+RXyXVKd#Ie*!6-FGOJJ480)X1# zjmIGNtwvESm7KF&jJlDKNOEOH)#9C@+y@N%` zK1(C!-X1Fc5ZbArM5m3~jEc=%1ftnbyd+)5B=YYH#^2&as!>hVFSqaRh_IY#AM>*m zqAA&9f>$RK>b4n+{8fg<=U>0=#X+06IuizC;3*UlBK8SI#-YteWd$$80mW0Z!VTBhW-|m#8XBqReP%CU zprV+&l8$F-Q&PcqLouy_I&)i%xAeX89iK1!n*JsO7Z`N7$;LYH3$qcKUv0AnT1~K3bc!LT!GytLNLCsmpp?!3Q^G38K7R2iYjT%mBMW(CgpqDgMT|H*XlQrKu<) zxSqrK$G-2y!R4>NmClR&@1T9q#Gkr|U=A_kO%%8C=G*s-(39b>5*GM);7axo#iNav z{{(|FlAABcm_WN}?sBtq_5S#ijuFb%_x$WP0yT-lzfq3?h-niO6U-9UfSwjBis0($ zg8t64Z2arTz;btPZU#U(@#VhGWB1kg8+A^w51@#LOS>}jOHxS_J`z#~d8w?R=y$zM zz|!eZVDxA|{d>cDuS+`t2x_%Vz?%qs&81BYtB&9y=!Dj4VCh^**L`ND`g&;Zh)7B$ zgF}Uw@)APWLZDetv_Kk(PkEJ187X&{jcKUempk_N4O?L8DNN_tqi!qV!s4W!u;V?> z-rV2V&Se9+vNjBoc+jO&ABh@Q#$t{4?>lC{lZ`pmAr9hx_#`rR6jY zc?9efOhHH`_togN+d1z98w3P%C}b+g`ZzRVOY#?-f8invBsXwPNq8@QEy_AdRmeT zis1RjLakJ^`4-ZBEXa7jvHr!R{UXE9s*&arjib%EbEYVvW(j6hh+yf0QXekJE1oW_VjGtpOuew{@`b35Hkm-4VwQ5oCXO=_pFpc6?s65h+I$*m~7c^>}C9iNe#dV4dDC|JbeICe@+ zuO(bam?u}BTYG*4Q@`mj*qKM0l}jt?h@$cTWPqEiqNvLLJUNPNU32!OVz5xbqO6L= zeW}&dNT?{3&ls4@kbx;~Y@gX4P#NLbU3>Fw)^p`x5*z>srK8kfP&Cxa$~t5U?>SqM z10P!r0jyhNh@9Es(aJJO*!TbgXP zIX7U|r>Uf*an{^m_Qt|q%fiMw+zQv&5TK(|!@|NcJ(ZiEmG#l}s^r$_WE%d**5F{r zr#(%vL`5Kr7l}Fgw|b(W#m&kxS>!_+pFrTJr}b~+BUfwZ_yT6CBxQdrNBvv`z+4)vE*0_*G}TEN1O<4I>;cnt%h1S`xXZI7cjwS=0Fc+ zRtV#@T+MD{ zFclZAiCAlGAui<`J}7@z@<#N<-f=0A^WZ}kF|JU?OpySCIfnLA0ebi{^Qlc2{21kA zn*%Af(yH7=jR)6&A3j`Mq@;U>D@KdT*T{03APiqwOG(;flOK9UGri+A?Q#~I zo(y3E5m zD}K{Z*te?j`UY+CG%c2e3CrCYUlq^pl7K6eK2DM}3#r^W;`upZ8G%7s%y`yi_DBgX z3SOEH31DJlJWbTF{*i0*i~kV9)IRMK;2!Z5Wh!fm#AG)&xv z_yMeysNd(N z%YdN|5!@R&HQx(ho2R}$PG(Jt<~wn(SPwJE4wS#3z>`m_Ev96VZa=j4G|gJ zLe9*>gyb{DomxMZLiEN7;`jA*(|3DyYmFL5=dRq!INRKYDekgg%wt9>{2Ccl^Ms#| zYcDd3)PX-j;vBD#DoM*PRN}#jT~Q-q`MR>U7Zf+ui#BLUiI5h|ivLqbz4PThC2qTQ z^E6EStg?(3)x^$+0Ue40-NDP&oPVcagu*)UDUl|?4Vg)82Q9^oOHtj^XYj<`xv_Tr zlu12CghJpSxx~d8hZ*t?2G5cAhZ1o<4RrKM2O$`jIy7vx=3fp%Cozr+l;#`YZ6qpk zPE)7og!ef+c;S4}iZ_H~;wInFmV8J}Ejp+{wSROrU_?#8EgU}Y_7IqnI>JzGs95Xb zBt=mII&kCE6IoI8bElAw{ZP{DP9w=zHEl6$zcP}9wULHvTnsb>m_A!>I!}nVjtJvb zy>pl{>2-c9icIsw_y}){*-xHQ+A^_fqxgt!B)3UZ;{YAuLWs&_CD#q$EY+HWnWl&N%#gl1jq%5inF z(h(sbY4tiOoOLb^$OJ$5*x_utxO`9($xgQG3kfDT%;J2fvMHj`y*vExynUSa9l_l= z=f4!^k`G$aQduRAJX004>^oe=Ym8N*N-C8t#R}uu0xw*Aklr$sn936S8alg!(i>L) z0f~9rV)mo;EfgyRy@WZH?TvfYKQ$fQdxHpaT~Kr9t&sfE@_;TFhYk=~e`-t80rpZP z!GX|c?PV-lUJ6;S;9@g^9W@JVGwY@9kci^EdGLYHRkIzOM~&TA+e$a4CYoy6z-F0R zz7i*yyT5u&yjr0U00M>Qi-g==Q)*>^=~r?8zXjIm&y)H11jHYh*pbd^8I!>DO9M$i z{?O!AKVKYnhK?5%(vgtip?edd=L zN-_UeA4d^*u)PE-eic+6f~Va7My7S-cvAwG`Dqh{qyp$ueTGLsRsFZ!>!id3x4;4K zMJ=Lbqt*%S*MA+gPdT}D8$fMJi16jZ!^1EoZ~+6mkHGRAC@aUh40D~GID=Lvz)kE9 zxD!PMg!uoncS%KH7+`)1z*yE24}|Bt6CU>i;Co za|*V=06YWCj zQ@LN5@jzQMXyn7^v6Ez@fEq&oXFS-X zHWep`YHf6kpC=k;h=M&JXL%!^-;WL1dcC3)!gfObXfKpWQK72Wi7$q-)2UIpG7XjL zj^XU84}(vRl#><+^i7gJ(D2IGj8c8lMj-Ja+-Y5R=e}zxLjZZ$M}Y|>55u1>Y}QL> zMP8+KPvp@CPqCJ0^Y$yal4s~!m1e#dvjuKrK)zQbL4A0KS!y(rZY;=Xr5H&H8xJuL z1qjLkng**B&wK1y&g}hHdDK$tSM*`v!(sakq9J1Vt92oHG@vUh-BMB(ftJF?bTo^W zc2r;y$hhnKh<&=}Ab?j8Con`C`Sbj*mWBWyjU8JqtNzkq`q7Ug)L7JM61QRcRrzn2 z|KM_tJ`>CIFV8k8bwY_04qJ{xC!w2vcLX6|H1gZ_9Q8w32?Y%Ut}DU3+9`Me|H>~F z{J(A%R3Xj7Tix=!Bd1y?6@N$3v+K>#zW%d=taum06}Q#$%2X|o@0X{kP~^f3yRDXr zx)S~G*!Sxdo8z|B?z;U_6$$D#HV>oRJ`|>)_e-maZpBYK2ZRhnA*>Q8!)88{z3&LI zssOIF5Bb)>;@pI3W*;{P6bxdY{CWyJ*Z;|4rw05mVWCFd`lKaS)y`c;1_6yd_1h*# zzaubFp}`N{eyJvQ_V(%(>|SazyTIENaJ4l8iNCS^fb%}?&Ru(X==$)T!>2h-;bOGRiP)N4kLXf^jXTooAJpJ~xcKl%i9NlEm(~E*N^LK1&n$)#H#=5l<6#iw za3z?^i$g;$opM;qg8g2#h5-eq0INjWYa*ViMJLruW{Ws)t%XXk@w^FhmFte}3YW70 z%R&+zX*==7_IwrDk$Gf@lvpgZErc3V0mJzq#Cs00@>o@W*@8D)_Fl?clP~f+!%*_F z%YgET96A3jtF%xlcDmVno+@+%FFZF!!!eA16`PDhRe97FA1-VnE75g&Xcvtpr)JBA z_L)GCjQ2C7B<}Wv7_if>iee{f&+6R!#Qq-&dGh@Bo1%jrFbL-uAAcU?@f3h|1`F%x zX%hvg`83%@$<95e2pkNKq!KE@drj{IbOxE{CVF_dyU{J_SF zDwtH$Qj`{yLWa))iFlDjEj`-Es0U5E7{ap5bSHO@sulX)?p(S5gN$ZdpdC2;6}A=Z zS;YHT<+xTo?Y%y6fp?}@wEDY@c8XKMTW3ZjFUo6jp4Ld4AM(%XMrK23D}$$dgNAVb z`(JF3P=_S>luuZg{Io3is;Uuj#xY9`Tl9agQY~*ah>u$hpzbYYskC0e-+OL%4Iw!2 zZK<4+gTE>0g3STEdwEl>n=)WkXyO#Z>tDG9orZ_tw|496+>gHh*%ZAF&E7%N)6?NI zD**2Y(7d<<%cod_%bS-9mp2Ud4lcK&%aauy9eNNGf>-dEZUD4;9icHGGY7DkzkUA! zu;`X19EVBvnT+W2SQQx_Z6;{25mQ5XVgn)P{4G$r>*xu94dipDrwCUC(3Lh@7+P*7 z*T4IJv9h{bqLm9)SB%Vm!35ZyloMutn@S-Thy`O5R2rLp$6iM{&OOm@1K9q?e#$F zz8T+;nZFZWt*~KeGK-V+v*u4<10Rw|;a4G%l#%3x2yo)Dnpx#nvjWJzyr5X>C(Nkm z7K{QT;*K#IE(pQrnfSI`m|>2Tq)F5Qd>s>&8Qi^=<8>2sMA0#Nkl2>ri1LWDB}__{ zCau%ZmVhGo6gqDy{W%6d-OU1DgwtXljzryjXT^D?#aue^w!DXPS@{n&t!8g+Bo1%r zx9ATX1qZMW0;7?aCbIZ0IP}gEgWu=rdNc?TIZfXyB|l!J6_(CdZF*^HCl}bK4ObT@ zukj`y*~x-Ivt@rxK@*NqqKadg4M|Ws-FS$s-ihZ~$dG>YL_@L8noNnKLY`ezpR=;& zplrCp7d%*vh{10)!Bth1TrN$tX?)u3UJZv5WxO~mCWF-@cq0DkP~0OpLD_NoCZz~A zj%3YdY-%l;iV|(U;p!iP(%8iP*gYvcP|%@OzW1E{BBmfhoR)#W4i48Di_LhFmq|Y= zI7aB~?7(qJ`EEE7OHPI64x9Pt4FfG&^R(sWy%1|fnw@u@*%ty8f$GJ@ z_;Ky75#O$_8x>4@0H!2_WfF)Y0fGbgnV=Lv@Z;5OjuxkOGQ@-%*!C$fZ9)%<7lTFZ z-X|pXv_1l7U4H7c^My)XXGuw8`9Gas-&Svr3)?n!<^~3KAW9IM@!Xl25bz3Wgmzq( z->i}yV!L0W_e#K>^H0ApYkv5g4v)3h_Ad`yb&J4>H>p^z8d(Ei2BOYX*Y>BLzzzar zr?2JRKVs2hUaw+akWpaxZY`@;t=_)jYAHMw^=i3fpfZ&^EAlhdfqdbnr6Szxv&Iz< z(^f$QTQRy_{*y9Yo9;OuE_049i!&4X5V3!o59~&h5H3iR^L}i$o^e{6d;v7?f?pVK z6hgInpRdqTUTxN<-GW}`U_0>(=k;3D;>KQXG}>o25{D`!HLpk3Zy{L4=)%sr=(R+# z7KBF~9`d$LX>!!U2G(^XH}JjDog#4wR51++Fq`@z0eG}%>%`VWv+nM0A2dE8Q$zvo z0o26p16GHPF!mu|ediw9uQ>ZAc*fW+l@hqcNWM;$K}o@pX&>k8-B3T6GBmr9pn3}+0O6#i%z@vaEQRv;UznKs(g|ofw&)}r zer%h2X_ug~)u_o;g`kZI|IrVjUB2^EzTvpKC2G~QEtq6LYwZ`Q<6lX^9-C%1%lq(? zCigBz(UW@D-Y)%S$ObKuxP>mJZnx*>lwNqOG(r`>(@(~~9b{TxK9Z|r%=`)Q1kOkqVA z-^CSV;qa1H-G6{s8$zz zuwmQrfDa3lqxW2NTcFpa!L^9*moH}+-2pG;F(jFp;@QBqUw?p2goPQFR$oRgt|MD1 zp+-P)c?H=B!PC)%c?S3Wzv9_wrz7{TV^2-n(*HwJas@Cj&AVb)D%!QSVyMd6EAz%> zQ~!nmZePhYfN`bCiUyen(B#zKi0S44h53YQazxfQ4|o^R04P)X>)&f2Jp}Uh5f7a8 z_7F0vX4K`=ed%fMeoS6*)eVe`w~s16mBTE0=FNfb1mr%7Lw3w+H@dvLTddw{db}R| zZV}fZfH#EV_)?_n>;Fj#G1u-n;N%qx;0y*;k0V!Wv5bBF*rvqFhCDpab#!UiPC~D_ zMI+ z%68(A58OiK%ADF`^yGbvJsY=5do}RP>L@!&E>Xw2buE<3gGSBAx&kDyAAdDd{fxXE|??+xg!%AaS5e#7v zCwx|gPh2hgTzy)*vM+U zbP|lu>~Cqq=k|qqIsI&tKn{O=LBE9OET+1=8LHaTViqzSn!;FoAZ^btxigVah;e0cmYo zt??--G?lZapW{`09c=htVUx!R)|{j(9HL)j!;8fEYxRv=3RRdjC4_lAes%Es4F1Hff@jMDZ3S!J zRdHC`9;jsQ@RNN1V)~x+^}T-gpk`aG)-CJCds7TwrKVuAY{|WX15;AM&Z8zJrKcrT zeymc%PExj9@w4Lwz5)XVRP8YtY+j~4RFY<T1_y-_V9ZFyP3r^bN%>YD$m?MfRxDx+vt%R(JiN`eC*-I_%Axc!-fD7m}4b2l#T zSH%D}<<|%6)ERReW5DK2HTu2?M2hXZ@c7&3ey<$-cP76VPxs_x#eH$@E=t^iX2F&3 zmKBwGRcuq1=yr;KGrSfK2p{V4B0p=ij!uG(L&5<8vGg{V*U!EE9@XE{3o{Xh&3wRb zdH$3^hwOzMO)mfC49tLF6Lqi~&Zb z5A_^wbU}@Yvr&`_#i)7aswV3if{C}c%jV?lDDnv(3>T831;e)esNpF7z|d++#43kt z(3MTJt(kJlDJu+@*}HK7De_UbTJIOqPtqLp8ujwZ6tgntxcy~%!GmK1j;4>AY*=XE zl)h`Y%cOx&=nqm<4ZT7&d4Z^klZUc0xf8XLQM34@#%8kx$vz0@B})VMPFd%-X3em7 zSw!wJ*_!)#bf!GKizCiSTHNQ!DDgKYJPU&HP$vzN_G{Y5V`8MS0)mHdoYE5+M`9vk z*9C&sNK`D<-wqENGkK)0mCOTWG^_~Xd&60Q^z~-TFW!B&(c?0skyy$S%IxeRNHPGR`RwjrcB2~S9@c)X z63yC;s&4%?@ph4Mh&*JAQ)U*p%(5F-_jpB(HvX-=s{@*dXs7$Xjq0`5T43k*f0IBa zV3iGfTrPJWen9twcOM{;6$8EUe+=}{P3+#8FwOtz^tmPZ4uQ*Q5QDGma9c2Hv781( z7I%PA3?KqdPrv%yFzOl0kH@6lEB?Kv43Ny1yLK`$(g^JAm6% z&HrdlZvWzx-vHZ$J)CRIxZ|LwG0dJFiMU8K@sNhGMxTjVRIXsLuA;1}V}Eh`f^B|O zmJod%Z|n18oLWVb!}2=AEGiZyjc}w*HJ#Z-+2ykqEjD@*9F>AxmyXMnFz-iOH1Vh* zOeTJl<(S`o?KlC)0vM`|wQFwgctcEb7;3TA0i@E0GeUx@w5Io^af2XwAa;AFt0zt z+@sNqz4ltY(}_o$V&|4KXpM-AEK+v(Z}h0C2&yH=_b&N_be~BrvytN!N#W&(m#%$C zaPd74?%aCmshlsR2$ z6U$AL%K_;hp!(wlUdj?3M4Pi7YbHt1UjO<6n?s<~$QmEMQQYUh!Q}vHbMz*Fvk_P? zHh@-@r^=_aG&9)|!T-pV|CIYVFP@kNFr`J8`$0Ze++;=y10+R1yD2J zKf2!yjit!NlSRcVBRdM4(A{b`WifexFQeYGRhLXGtn_XFl?r zMTZ9|RxqSYy&iAl>nd+EY5eX=8d_SAlq9HA`XK4;&%C%Zj}q7EC;%R#${tV?&zU8n z;}1*t+VyHU>R!MVCl_9kDOXUv&885Wc3+Z2G5|>EV@}i6c{Sl25a*>A*S?Gvp~l+vzml;~#VU(>OP#czK~Sq3lQgea-ZGQw7gzoA7X3z7I9K`7v&`(sZ1A z=>nNHpVXzuJOV*3C`C6)QLwY4dQ6&gpu%g@gRJZyJJ(H@y9;4*p(>|XJwxQCTA>C) z2;+zO`4A8El`LA&($0)!BZ(Yea=_$9ID<95<{yaw`6r8rW!Hofn)-0OCsN$lERPdw z47D4#u)QGP${Ih}Ag;_oW8DLhWVkZ&H36{WS9+*_Uh~ZQ3wl6&Q5lhK0DOv_L98123k+-^TsV4q6}2e)qz=f z5fkI!n3MpX@c->$_HSxS`%=NL`DIi5y!s2uwvIiH4G%pEfUzol47h^>lNJm4Puk2P z8#^yRqES2=4-jpK#=zLhkRnj^6rm%O4anq4k096&d3*S^Kxm)iyxHU13uNqQDR;B= zOE?Kh7$Ir>w%G@}cjFwhGi%*K8Jmo5>X=lkhyUj*<3vn~z5Ph$!LIPB%Y zo%4StBv^SV-;pfO0}#P}OD2?(V8wAGeLcM<2%AwC9%#|>>0)v+)?)ymo>RkBbY_ zV`Y=Ft4pbe5*{(k4N*%4QQylSNyVkA`7H^Q!e3B^Pt;3i!Y9MeC%6(4PL*I7%XW)m z?pk4uWI{k)9n1|N!F;vI!H-@H(PtjN@dj43qAKdp_q6vUw^zAD%Z6;^wzZ;le9<*r zJ(MgESQAwQ97tMbb@0=Ek5~TU8fP1HoP#L}gl0Mg0feO#=tP-Z>UUbW=3(}y82VGc7aiC?@N~>*GmVW>PiO;T5 z_E|U&(}rTKzvx$rqMUFe$xLwC5$Cj~W(oO5Vyy6yf>+!AWhcqaB`GSqa0IMl=kDT9 zsv6KLH+@hE|9Dcvxds+LQw8bi4775!LGbEe!|2QG=p^OsI(=1dc*J+H_y5Gt6p0&V zLMiJ0`IPH_Ww5G{G<=64yONeCb@^)<^ke*In?^Cslg4xMWg@x`WAb?Vn5bwQ36>ah z+{?WF*QsWu#@autM@;@~0!h9SV61;X z_|W50;<&w~V>|H?Y>k8Tjy9(JqnV50FIVm|EKj-}Oiv>mykFiu$>dnEJSc86z79Q8 zULN@h%i-C=LA#xBNt+0M%j5|0lD-Mc6m$$cqTU6E$B2A?swBpyN z2^1JtPAvjK)l`P%wKgEqkmfV46W<)M0)S1W)2R-2ZBwa)`^9e$Q$WziSmR%6=ku3{ zsp_vz-+HVPns4J;v6U?y?Cg(!Ta{;i3Lrne1fq6;uGPqx>T`9nGANgD{yV_s_%1gG zxCVE5JORQCX5AV<$27yvg7x1|iV`WaB8HTwF=MH$$ZZ8vP$*3RdcqcyvOk2Pp4&iL zmGw-n5Wa=^BCK`w<`#o-Lph})->`7coQd7}zrJ8(401vL{a6pE$Jerw=RXGd5PUfK|#Y@!S9H4DrW z3auXx*UqHuNu6-9!31hPXEzg>xlbz0(5>cm=7ra0e_X=KH%j007xLD6Ry0hc%4DGgq59~P1FAW9`CEejLb;}sJ@(I z^wpFbk~)`)Q1(lIHlxy_EU<{p48#qBPle}BRIlwB`g%hzidMrvKLA_4@(iok$X_Pe z-(`|LyQ)>GL&l;nh}YT263!f|DgnovGuYye<;DJv52A{ET!l?@K|o9f8)7d^B9fY< zj2qRqvOyK2lBoVdD{UJ17QWfs9(*S)Om-G!7@<*ggv4Y%g(?9fc$oG~BlaPx2#E$8 zYNBQAwpWfTO?wiDdqgklORvxtI2nr|V~J0r`pj#2jGePeIv)i@=%@~Hmf?IJHk$k? zFJ2-cFKCtCggs!Y!0SsQSD0pml_z=K9FFklq8~R%qX(O++3xv{7JI6xR)7T!`}!~{ zag~r794OfG0=-w43BAWtU~8LV@ekVi@7S>TJ~bO*8}sUogvvjk8=E>K+J2o8OoXS2RSelr7I2 zB}GlxYY$PG&NX`L@=<)hF-$TAFGleRQ5l6&V#C#U#oM=B#x9ypa=TVccXo>&`SC~- ztff&0$*Xuk{P+9to@!9q=mWH=1Eb0dYrlJUF58QkdTI~c(_l%@`%{IMX>Q3)v%h>S zz`4nh�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⁢168@68{cxRT}x9F5yp%4NXA zCF_=aT_n?De9SSQ-;^&=#S_6UA}F7c*j`4k0aR=LwPB60+7`O=1LDcV7zYTSG+$i( z@&YbEM)nGKz|GZRnj=>GkI)HCQ8w1UUd%W+t07o8TeZ`-JZD=^l03fF8+d}Z-n%b# zE(3;*2b)(Sg@HgMBZzhhh-zo-tOYDePurT%S;d5$&sRL=>^Id~`mXTc z&2ZD(j4sTqFI!q?%VYz2Dp2d>GElcp8i@k37l;WajSc>OY=T7o1Y3e(cnyu;TX4x| z`JKaA-nQ|1Q6tRd?&6VJ1ly^<3Tpz}P_j6X1-3|E7e~&AZ1ApHG_tDf#D9>FGKB?a zMJXexu+wuAlXS7ND~%2Kr~pM15rT}1vITC|rrGLWj;SC@XIScdv}9X}g5PpI4;W_H z)F~)jmNc++z?5mSou0?Ux=fIYhhy^j?BcxX3u}$$Ii+)bbeEw2&d0gnV5;e* zFhUe1bv4<@W0PC}j6rgTNy4KGT(!O{)8i#ho{W(UrMTkF=tgrmHl?axc@~9qx^sI? ztJU;{S^OjgnM%EmPC$xMryb|t{GL5lU@Ff(;P8PRRt3>Yoci zow`oa@j4vS3_e1ZHTUaFft--b9rd+GDr~O+F!Y4TK!C;OoMibNp1uKAk-eS~wn-#b zqx88C_3CrrE%lvFD=Z}eSnlF8Y*pqDv3pQcF$`Nr#bdWWsl1c>I z!r9N4(HVy07xfAE5sf6=YK1^Hj2$35v0o@df|; zNtB^5&Q)5JzuTArYkS=r)9IQFJPT3^-hWLUv+(j5K6gH>3*wP<&eh9GZx?he4M1Qn z{qDBFzHyyVwHe1#G#V?<(8-WxVzk}s!#r5bkNlM0{Q;(Ym2Bv`(2!?6p`AEI~&+wWWNA)_{C53whmc7=f%c}Nof!^CJC8;$(ZQmA@?{GfH z&#vWl;JD0^R))X3B3kI8pxg3w9nyw<2PTrTiAa%`;D|Fy2;$MJG!l%(-N0P4*gRvg`DKlyib1e5DdF>+K8sOZdJi{_o5%S-i%gR4MWuS#>lvOTI zwo`<`!ZS4SdOr^#MLe@@-}^VIEMk&I8(f{1?}6c-DL$!qbRA37-Pmb~NHjcMpZq%& zW1iWVd8#UFKf|h8HC23)5O&R>9t z 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≫fD^e#kML1oS|;Wt7A3+I?-*(C?;64;kDa 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�RL1q(1_Z09ue#X>=+2=;8C9YU)wcCHZWPx|5PAYY~@(>!N z@hC787i1#}w>`sI(-7_g8$`k+r=f;)d^@vSa`L4DlnPU?#5F-H%U_=*9evjxl%`=V zJ{7GS5ls zp7_fd?SiDi#cr4MSB#7BW%_UulGESHX-9G|Getu@dyrnNo6?`7K2U!41YXx@oIaf!og@OmVp&mkNCv z?1c3Y!(hf4?*zo$qP2=~jKOHWPE$*-NhGwFa{48IPFfz%hrMY-Dz}XL&@)_CRkBta zsra;@mf;)6cIp$I4_Aqn7IX;@jN#t@;}A~wtC%0_M&$J;9ey>sR7BZZ^d7vN7;9h4`Nq( zTw)wU9S2^MW#MPYpvD>Dja%4fnz?f~x|AujeXhW+n*~F)io!Ini!$qpjg5^i%fvpu z$HWFF(__gS*W-Od$AT-fIxGsu9^9yO6-ZW;k_rM^o!kjS6NNy~M=vBi8-f5!?Y8e%QwoT-~(8q;@-WK%dynQ7l?QBtSr?Q9oT zs<(Z_eRO=~pQft;(-}YgmC_ZL9r|+z(v*hzpdWl71+Hvcw@BdE&tpMEug&sa4UOCR zCgGb_9Uti-gsMkT$O%v6Sah-%mUz~=KwHNw!D9Ns<%lB$=m_~W5+r8nJ6xaS6)q*M z)6t&;VX2Zqpco|tf0S&T0{&Qn`9MBSI6NcQ*k|ZfRb4N~2*wcQL?bQ6MJ}3;U$V#) zd!TT&`|*=NA6Se3I?hgjV<@2EN}Hp z%H(F`H2PrbndF`+Udj64Qn7qQP}Xdw05Req>T@V+bKP;2Q(>R|Ov{$cR;=Bmq7Lqoq`F#_ml~>PsJ718>sBjL^c{g3gjvEtachb9aE@J|aS*<5 zw;J`byXpIKN)uBoJvgSQbS=xc>s%`n6D@Cpfb3Zpdp8_|QJ;&7i~C)dfn2ODil&0N z^2JDe+T|kFA|Y7Zw1Sns?J0gMg|0@YOL$!|O3}S2im4Tq>UnrXsdR<0)i%*Q(+JRa5_VIo+5VN{1{5Uv zVQ(3lGP2aEpxN0(5n{DNj7gY-`=C&8#Pe^Te4zG1SxhV~_xXcVv{}n3 ztQN_IwW_49xK^$ELuZ_)M73g-M#lTrYBfWc*~*8mt~UbJy$MG0Q2O8Y&R zjIzx|zd;iUu<}m9vRdoZA~0K74LIxBV4E1&Qc{a+O_)L7TS;p%pHC+;Uq1t(VNRWV z9e?Mg0c85|Yw5_IOCyS~l^;2Di`1~*;S;&v;43LNXC2`Yt`8@?tbU#Ib z?qu7>OA2TvoIEZ)yvb|eq3u@ZqnJ#|x(E|I^+YP(>0!0GwJVjfCZ#Xe-R%*LzgZ9v zw|=N*rDc^mQPHqFgHSY03+_3$jzhfrq7kjd*>c5V)$)p6GaD~LKfIBn1kytd`51Th zv8i*FfF}Qxn_621#{LU6L57&q>+pSALd3(kb)Mpyj=CHwfnfoW7aPf}#IFiU13A|U zB~&bo6zsb8&J%IEm7z%7M$YYCYAID8I$9~&0m1n!T?5jf(S5x&c^Poiy_)(Lv<*b| z)lMOs{XPK_sE8_b6%VzRoCt06Jd8SbzEcc&VHJ%uctK~cmJh2aJ zj238%-=1yaE)gfqQF|oFFp^?!{1hnroaIx18l^9qAV1W@q={E>4iRx23SNX>b)4ma z+(r;3v&g4+hVQXLk#lZ51@o9aZ?f)mK6P7=Yn+q@+{xl+fdaD0-uf@O9%LTZDU-xpc z{9(LY|EMVbNz@6;Kj!25AI3G?&4DXPZ!tlcNbTX5hD7pn0&0iaB=-_#1;Op zU?;3U5n%tuPX1qFCxDnc{~|u_JKgvnefu4Sh0(3K>xSuPbEMKg|Ec zzn?hxGY9&M7ZJXz0)V`KMql(4#rR>P`|d~{$x!5E;8hYME|x*{>e=IeT9D? z)qkau|79lCUt=e%0J{^g0dDa78CF1?L%{aqcK>=p0Ep2adhI8b{Pz!n-_*(fjnv&E z!{13zCZa!+pxED4G6y2YuMLo2*lfR5Ejt6pUqpXh(O!xmW^?d5E$`n2WBt?;`yOA9 zIR@2Rt;6!QT6<)xB{~ml%d=0%t}uP9k+Mj!C9?)rdUSrVUy>0$Z7`yM$<2vSEZ>rE zd;3~JIZIP(<~4f6g7SMK$&2Gcl*i-v zB`D~`xT?{i$~&D(JheEZ07|2kc8WoOa!#33UgwkS(m*s z{W~^TS-@qn8*c%ZF}7#{E}Lq4dEQO1eYXF0vt;{xcaG=%p2F*P<(ALW^M0qG>fZ1h z#&Xdie}dlQdv>4a$BSe8yPK7p%l3BmdesC;DqysyM>;G`UJ1!X?Lm&FFx=Et#9I)R zwDBotF$T?@HbEvXswo=0n(a;=bq(*wt-b_2AMg6c22A=>L13YA$}Okdx(!_&*qm^O zQyfIL@-NN_c9*4g+L9G7;HF7N*i9dwR$o;Z#^jZ&3{fT?4Vo3j_c!T{uC}ymMCkRe z;Y>!kX28F*Y-}Yu$;(?OZ5uSFW5`P!LMM7BssAh%R-SSXoynKVH~hSz)zP^}tyy1E zGIBfLwM=epa15ItTNl8i>Vq(Q(gV&`EJn`>&9LTdA^`*|H&TL)C!HQPvw%gTn~B|A zKVy{;Z+O1z3bJ+(=j|Y|dx|jDH-z=6rwZ?wT>^(Qbj?*4$Y*8@HdH75kg>(6pJ3Z2 zlthTCFRdNyqre1gUj8(e#GqJ8P~qjg8*?r_OTd6#Og&~i!DB^)l1ct!TKO7V2~tu+ z=me%`bU*VQrzq}Xwc^jA&BenaSd(t=kMZT?in#p?cWLs`DOj;aF|cV>3RRhFxj z@207#JYXFC7NW|EBIl_^?o9*DA|^mGs=B}qqG6Y`dn=SIH3lx307*?b;M?aEmQ&lW zoS%J3iNIAYQ<0kHk3Z9M(4*G6 zcFtTL&^K4nC>@usjEr#zDYYAYz_go9Dn8AajWs7G#r3JcEa^P%>0m}Gros|VK=FqC z+C>L?vAyT}*aReV{?PO=>g!pFIsDouB&mS^`EJ01Ug!lrcDMO9AWoNwR=47dCfsvb z;{E;^m&RM)v@Y(ElS|-lmz_1$gk>*u1bJ!EEmX5w4G(%OiG*%VRGLS}3y_N;eKl|` zOyTc1We<)H2IZf&%paSS@1YIYppTEQJE0DaI@@(XFFjk*c`^N$ChC)@JzF6c?_)_; zbfLs?h3{rU1v190)5kKrD})VJ^+laktS(uE&?V({>4S2dk~ zf9$=g?Krk) zY{$9tV}(NTMO4+wS}QZF>d7}ti}q^vqR2>Ig-|Azo8P$13;XbP88#%?jE)Np8=}d> zHPq5AzjQ1MXb1-zJY;F=XFGz|9oj*xxh~d#C8}N5i|jaEvx@JSZTO%Y)u;{MMP5Af zchZ!96d9IgHYvh4t2P&{bA@{J9)Cnv2BCfR;U}+V!74AG!9wU>Oj&-ts|iW9z+AjMrU$3QnI044$y6E;rR@Is*iT?Qv+oBD^=5 z#D#JVvNNM8nwPzLcyGMv%KY-YKDKl^byYp}gK)QG?=^K32eOc3lZe1WdLuHBUoVt{ z077Nqv|m()b1r`OwTn7m%Xq-DDqwull0W5zAFp~IwD<6il(QWUD%_a(z(-vwIay-t z2S|13mWo$K;?-ylfDUzN(bww59LLGiI>Rg`L3q*08xTEQI7U6QRQr&UmFUp7B!(Pg zkBi5H>Fsir+{-zM=Gqegv{5Pt^VwyiEQKE})ai_+#C5=Uv>}YRw*UFv)T^^X%VQ$mFV}Q}H z+X-Upm5K^8MxJb0v*9bo0ePam%ujxKiU;W$j>$F_P zu$JuTV@y)&b{f0dU`|Z2HMjVKIeY;vIS4wv^D4(gY-C?cyi2UIHBK$A4=&CQe9E7E zyDnjo7Rq8%aqDi?PK_uRPzGNNd;5eujK6qB%U9hDy%k(QZK3qS*7VV?pb{WnieX#h zn8fpf#x1{nwS&|+jhY7}xr_0W;y_8~{^b7tc+{{Y3#vH=1sRmMl*M;!E5B+Q?tK~- z=Iv;bxU_hSO*k}a9+HQ2D%9 z$r4#OAjEHOE+HgF?zA^Z2}u>7fa8W1(U-^yMeF0ZV08G$os#nLsoEDTh7i(}*DJe+Blfm-h0WD~-CHy#njx^|(+KHPv$8%t zoa7u)s@N^X0R14h+ksB#C#$7StRbGu^!ji3n`s zxafCbLwe&$(TBt5gk+622?BlHi ziwcwGltI98jVv(??phw(%4>V7v}`BUt3l2v^=Vxz=xd-0mt~PEGZVFx_%t8OU_R=a0{ufCQ9HF^kT~ zhB?d_g=PHKGQ$@K0Cuk7%@%&O7Detom{wF<9{x)(hGAF1w~YL8p%6s^k#eBOjeMgx zKP(ddi`CK;ICxjP4l-;x|3_e_XwLy zK0|O6b_3DJGWgyBSW4HOu;L7q^3i$^1d8ke=gB)V{!v=N&i3CaCx=@@MvB*d5{;}nPB zYYl_zs>YIl*?p$t^4~w298B+WjZG#hk>*U~Kus*07;{e{?Wnm9X&gH3PF_((^?TX#Sd1U?5 z>n0wy2BdWv_#-tEv>IDg1?%>QPvqFrR$1Y3TyZgENjf0G(MgzXA94fdy%{d4o?!cV z#UiOP4})|e_0kM^uMt`})d>CWg$gjf4BN%>rTCbH))xe8@j6r?2A)A_clAUSKRl5* z@h?D(u-J2&hn)2bnrP_)QSP7yJAd*>VpJ7%)YC}HKD>tI?_vNC07k4A$`Q>gjzBi( zAjvS;jbn9BA!WgsLCSCv)-=P z>RYTUb@AgDMiqFB7`C_P?BKuVdm>I&BX9|)@)QMeIAl-6HRl`lO zRwSkxhU-8(2hF^ywb6m_Dy<1yu9xt0OO#2Gcayhy`3J{;Kx1^f0?_*b>&)8;Yn+sY#8?TQS17N z+&&O-N_9?`Dro#6F&te+BnuiQGb|%t46B=fuc8&oqQ^z^@sb@1SD$64OfKjYQKa?_9njPiKoQHzaagikAmz$~J zQ6+AH!|ij^^cEmhg+KyFk}_~3<2X%yA#^CZm%}_P&7E3Y@`1}e9VIwn)+G-p4uw5$ zpiQs~=D@1F!rjY}lpBN;0we~q$0-{vr&gZIQe`b=ajmQN^rMyS`l~EMU07$j^!kpL zBVb?c!z!@i$aRmh%ue$d<5Q-;0mE% zl^y!(&ZL?>OgjvRIBHfqAA88w>`%Fyg%;$s-DWHR!6;=ju~Ai3BZb;bx0IxO8LW9H zrwDBXr9xP4Pl|p>W=<^MR~3@pF3LxiGeXC%@F~=%2!^vijBXjB4MN^{Q`NHyrr z*R{?}$@!B`^;Ry$)EjklANyAyQoC7iEH1Po+m0a;=%qEx)Zbf+!b>x~HsA!S`0g$F zZmL9a3ydHg-fGpWeiq+r6z4;h&UQaboK2iR*~83XO4eia>VXCZ*2$Gvp&%ZT2MR?C z13=jUp^ASvkHfdFqP`U62aw0Y>T3l`aCY*ahkgwxqrQ)2?+O~LSnap&Rq92F@Pge; zmI7PFW>d9qE{qU`Lk0Uz&g}GoH?}DypdNp?(YquzO`v-FCkMKr3H1TdU8uLl4iQtA zHw@NF?OI&5BVycxCD4GhEZ&CXHqYSt0~;vNOR^?@S!6JhvEY_Bsg_y5UK7e0SFi>x z*O>P)53opAv_*%w46(Wpb($Z$J-UqBkOmGYtX<9w>E~;Hrf>EWbs{nDU68~5Ha{g5 z{Uu4J(O`s=K;DU7adv9?4|ZtoaX)z7s>y;?AS(7M&+$2GOvf(ugp84KtoxOEg#1*h z#jb40s$C*@2y&4<}wFu?FQB-TkR11b_?MkRKT^XTDx+O- zP8;7lkcx`oo{ElfL^rfzH3;Qmk*foHJ+cb3_dx>mA^k(J$j5^PdZ`AWdQ@V;f=8TA zk%Z?3X*K*lDBTPpz>C05n^JvCV39UxJ7p8E9fC)$jx9vWfPsryB3`Bn*Y?xjRf&j%TM{ONxd8i6)yvUj z*b4E*U)esCemC+p%qz_njm#-P#hv3$8m5BZfH_vZGlRCg+nZ3oXpikQLPaflqoM+d zAl!?(wNWTC>6DOW%oJa)szQ*spO_V-Js-((ASxCY(Oo1Wz$%9X#Xi-bzzAi_W;`#& zn*szM2S6DYl7_U=L@kO|=IQ3INUF0Nf(8$R)`L_kQA5!eNF{_brCQ1GpyoVU(b1>J z2f}W4L6Yo;h+$(KTx(@ZtLS#uYCHFHFh-WadI4;P zwz2h5C#);rkhs@rR>Zo~g93sU-4lXhZVyN1_ud22YimwHupt8QH{XJkL#9h@ZnK(}g8^E{j&N)eONd zMqhDkciGD}xf_WJKZ*I%RuL*$DXVuF)lpY@btJdI0p)FZCZFg#R2_0x8Kcj|14V|E zwr;lA>P_n6t}#(ZN2R&-QAE4w2$bc4AOSrtL~yfT2*-g)9XEZ-NCjCtu0Bl%LFt5i zNbmBDYrH`I3Y>>OS85#0A|Y>pZ!oM$dwL=3jXy(7{j)E~5N%reCZZtgsS4TJ{5qBL_u=8dy2-oc3>i{f<70*YJGvMlnRYaL5FlV=DiRyj#(;%mfN{0gl zUV%|Ag;8!sttbYg=#0-m@gJGWHS!9^dz@DDH?4tS(Wyno!84n^D%?kNRf+u)s>sYn zT8NBQ59|>vFtU0;1m<>Zm;4K&woRXtI|m9*&SW@fkOBa4L8D zlq_0zUKP0H;7gNcNAy>s6OB_eRBZGN3xp|!Yq+WmKbk&hG*jcI*f|#f!m<}Xk^!s) z3qMzra()hi2V)Myx&9J+B~&eWAIvlOn$lrtxxFK3o67=quFQEQtconE=a!k~fL7I# zpq=hT)7#We@7(C%Vk-I*wIMasAq|e!s@!#z&$k;eUQs*mc$a36J^Ab88zHrGGTMMt zVC#aG@w())*{()*DG>$TD@t$JJsch=RvPa>*l?!23_->FUQV1Sdxzt5e3MX>E{xL= z=lfnhoE0Jl-VL5xKuHklkIzR-i5dn7IB|I#YiZ@SI`VranrtrQZpWi&X+c(!dj93} znWJIR6W_Z)l5%SFi)d+F)gxr`MYs}3Bv6HpCdgty-OhK_z_#Rk6Jc8mW2u2@)cp}w z0ch|h$aXG(VZQas(!e6j;puVC5LDf|Gh%0FN*K(nv1{eIn#0coz%S~eU3tG1i$kK77eNaXMY+RYA3nkEibOKP}5u@PK{m@Q3j6j zR}fD$#j^mNQ5hpI4z|OU=C4_T}&+{$r-oAV*JvR=J~6(2vr5T z6w#zEL$ICC8VsLlI@+Qy0b6=1hQy+ZZ4up8ioxMcdCyd35(_d4{2id4isTIlSL^C> zAd-sYk6DvUu`Pa1iNk#sh_|ZqHq?Tko;7d$c;f&5C zNqn8DBr^O$69(N#6O~n3h|WJ%I4E0nGYNB{R3RwjMPG5A6O1E0-pvKb87A{eDVA*t zq%0CsP`jcva<)ozwqsM-%*A2!(K=3Js?_3AsR;Rck&U4Sqrb<nI;ihxf7e0n3l0ijq(v_~A@P?Ar7lx4~<)>)0P;PQs+c$z~&&i@ZqY zmdv3P9N*68-AoEy5B)=jkmsh3XnBoNx||O?>2V>$~n$86NgQ0snTPP*sJ`7 z$38@_T|zyN*ZCm^SeQ(Pcp%x6 zzljMNrB*z7zK?R5mo0`zjM02-&K(oBRu7>~PS5;xj7ygVzpihkPDYMvq?TvLL-O5H zYQA`noG$hIC)4E5fwrrz7`#@QizKKJWEGZ&p!J}`tQ-fLf*^(*9FCCsj$sGJOGA{3DQ-(SeS_wP|Qjj#=1Wp!o_?o*oj^``Ua_)*Y-l6q&#}1s6dR_K zm#jqIqw>9Ddk|?myOI;$tw=e}TXNp1;7pz}30uLC2sklqn+Sz^5d=PPqA?R8d8YNF za|+k%zEqyW&Qx04)27U5d?p-ddEwC$U+Yf}A0G=0}9lRc9D}>wTVSVj8Q@izP}P^_DYNrchf|hRjZH zpB-G}Fi2HGLcc|O$g1(t`82$4Ag{=qh077Jc`fX?7c=S+a348d?ku#2j%9P&2Xvc= z!iK=)CF71f#V^ey{hOW-I~3KYwekA^SUOMXIF869fwUwuW9(W6;SDBr~b*H zbwqGWKi)$8+3}7$$8*l0>$(;A43PXx2!E-W_d7HJ$G;4z{BvEY zzZ;4DYY+qn+n*?Jyz7HjsW8DUw=1`@q4X*nJ%Lpib^~j5K*ahzNhc=UdBrM7zZI9` zBdYE^^HW85%=Rb9h>fiCW=gsw&svJ&F)@z{=*KXgjq3NE2}`sNV-sy%UEjnVy%fX^ z$2qQkB4`B>@a4VR7`uC~VdQCl;~NfJDLc$inewR46u?y_^cy4FF^rgsfz7PI#aH#n zB^5J{%V3iu;xEn?MI9kKwe8W6L+;Y}v>M$=#gtA>D@NLCOtBEzY4I))3PkEDg)D~W zqevwTVyP;*J3N(Iq=h;8p<5?T1XZ%5gS$|Ay+{rv3l!@zpl+d^=F`rEEP`WVA{msy zJ#G2j67dH;#VBl??&1Av6A{XmK48&Frbyh?W(BUH#Fx@_k+0y%1U6in5|u?~C%EC< ziQaIfV3|!x?h3?c@%(2QqS7R+^;*hH%Vo~Z!O_hi$q;}(IfocMPx3@jdyU2AM@Zgj zbg1|o(1pXjig|qA{P=J8xm^?4yf<44M!^Y~pw$?sdsV2wBC+|uD1_>OmQ?5Nyz56#M1wAlu65um+yV|iaUlFB8z7BehTq^&= z!XPL0E`(`Rq>s_q&{r^}Ju=2!dE!S8rtGf!n8`7H^F0_w(%ewMr=}4EB(O&72Em$H zSO1GgxfM{tMYrA;wQsVlFI^$+*f6KsyG#4t!i-nIKL{d16)_JF9!>VMAXe8JVx*_B z*;7skVQb$NLciXxlAWtg=>DP*y85_uak6p&o$V{$EoSh0`~BYr=>7Mr)!@_4ar)~D zq4;4{-o9~{qb|GMA7L}iw|0a<1f@T~!P|nI?J6|Tq@6NBq?*j^KE3UUq;z5~Ns;}Y zNGr#`kj4Eo6z-QspYP)jP~RUZF#X-$_-{l*-_QR0Xeh_Okf8myR0!qx4J-RMv75iz z^Dly-9RC<~`sl}9i#Y#tF!bGUOuriMS1|N_rcA%i_Wg4Id^fyz3H~)7 z`VAQRckhP3mYe+FD1?s4{!**qB>V?16z&%;l<#-BP>z2YiTmf7-2V(l%f$63@@+2i zALN7;p_ZLsW@SazfzKQQs$8Z(u_`~$7Tmmsx4y}?M_JAf!-0Zg=41`W@yGHi34hOx zlpC1_9kD2}{3C%-_N|Gy^4D>jIn)P(Q(>I8On=O+BLa1MzOJjbjSJiY7rM`R_i*>~ z{$Nv3X2}bjnCgSgvlIgU?&E;53Tld>VaH^=pM4;qBbPCph0hro{rT>|s`I}_=Zwkr3TJ$f5WX|8DiGSO{e=R}z6VYzYe_2ZP=OOvsa7@1%@7Iw0 zK2xS&XZt%L`CYX8*TDAQxFP;(O#YLSiQkt9rTdf6uf0 zCT07ZJG*moF>o=nvc7k$XW`&v0I+er>%1~^GBE(&wal4`SU5Qu*w~l=T>q1O-5HJT zY-}vw8`{6OmS;EO;sS6Pv6(O#GBdMr7;zdJb1-vqumQMCS&dEDxj2kXn2r8I&wJ)~ zclQU$0M6g!oBxPq*xs$c!T#QCfSH5s-7=i-M`vN@VgRsn0GR(NmSN{)eXsI0})O=D)U5**Tcm{#a>y zM^`&$h12m}RMsI2QUm@B(}2nE1e@`)T96%^$iuA`7wiOV;n|ny23@jLYER{<-_^|D zgm;A=U350-Cy8cW0}{`ho744~+m|Mr0lSsERoiU-_UAd+LE$o=tHN#V;i`|+)1FU9 z?QPFfh>dSKl$*Q4Vc+bPH+S78_H-JPQME2Po}WSmmV1Bdzg=E#5pJF^zR5zhURAAH z$v5Kg;k;fAW$zQ(hpIKk@@()}oPV28J%43}2OE26c)%ikVJHpA@>>6(4eF4)r_IVBa)MDt%Mr#0fH%jA>uCCbwt;}cW)Q?JG3*EI z6dTs;s8LP7-22wiSe2$4zrD#e3*@c0L5j6;1w+{BH%9ASf`@TjTfO%7c)7K<_UY}3 z@a=x%>=VVx%k|V#wm|FieVm3%qkee0Vfib2J<9XR+!$lK8$&_1ZTsufXGHB$vcBp4 zQvJ6bG4h&dly)|KtFISTJvK9a<3_8}ty}T6!JF@F&0Ro~I`l-LH|s7WaQpK`_Yh+{ zf2F<^Uh*1o&t}nZEottg9d8!s4U|e7sFDpmT{~=fM(~dGYV8=g33+`gB!{IFbv#Az zco)?G?hMTUA-Jp>^(&I>byT51KbQaQ41P_%;^LJX8oTC z8eUiw%UL9T)Y-+SUB}WGJ$EE!}d|k-Lf$OVI z_6-x`b9!5PRzmbV4Tyl{J$<2Aez+bx;z9O2g$?RWXvKR@PKo$B!~|M9QX2L=lobp< zH^~vCMm`4y2C{Vf1Z8^*oUcSf7dSvL(JbAlhVU-Bn+p+ zhDHU!%rXNtVa_dPCoP$$nXrwZx)_y!fW>p5iP9K7-@6s=@fxND3@%YtWqT5xA=t0t zh0p^9elC?U80={}LkJOJumQrQ&cL--@RETmDwzf!8*5p&P-FEg%?D0L-`U5gxb6W% znkH8t1Z&g_@0mTfh(HYs&t5Bxl5&ymkx|^a=D5Rh76wN|FpiVBnzcqu=e@iM-?Ixq z26;Sm;$vC?^rq-q2@8S^Bc#XYkr6R5i+Y4*cA#k&m$8cI-sq*!%bMmVdlUK9c}~fC z^sfgcvFh}DAXY#IM~ifj#J6(B12dqnMOW!&J1&_fa?gAjV=zRCqy&{dwFDvMGOH4B zX3Z60CnIxCbLA`cm!Ahtfi~vC!E!~HYbt<0b(XYV!B$B20hD`oqC_4tN(a?i<4>yn zu%{7onJeu4A>ixz&?t?nd{VlIJGv0AXyB%?ozM%Y%V5qZs>^iroqQrBKwf2(k5S(P zB!rmvyx>(zM%#*LTKk!DJPzS~dB%Ew8JpWz!KSc_EHWdutEh!uXDUz=+Ku@AZhF0d zY|MZB2h+ZX`Bmn+rInh_Q}!L_zJu3m)UA{VB2N@u7S%OtS!`j;=Fb;x6-Zpza0l8d z@u;6Z&mb#yV9X11QOC3yWO2Ll*sLrkD6=zAShOC=m0-u{AisbD|IMqr>1v+`6--Nxk`}JV^S7Q9|sucC5&1-m?&MMHi>rqxtG3Rca)5>n`D{;n7gV|)K46P4~-@8|z zcKgK-;xH#Z&#vd0_`r!sF<_1)0tZQw4xMwobw%IscOj%`|252nJ|6$1U1-rc*v;-DX{O zmQ{ib$=<>8p+^?u^I(DL06Zjg>cm*COZI+981Y$Z#+W6zs9e%DEzGX>ejAY{xRXZV zef02GFvYEIodc3AiJm;MjB+j$hn7;VX}eLw)G&Eg^opX@RE|duifCcQfy(o^(pxB#x$W=4l9Z<7s_jdR8 z^0skHV}F^=NHt0@sczvQdx)cESjvEE*@+RG){-q-g~&{p7`!Ap#3JKXzmJ2QarKc~ z{@^(|F>JebRFSiQZwR6(xqNt!$#`!ZgYwO&(Kt#ty@)i~BC&vI($CQAaQVY$X4RsT zMG7lo4i{Svm*y=z{);a+$m;7(q01i+TPiAWJSAQls%|H0b(O@^8?KS_vqBIs~1y;8Z*X`vUC* z4sA_r5J%4D`_x(`{r$(J%ZeMZQmJ+n^~%0~6ol)l7%*Ta3wxiXwiW`gJ|J)LF@M4H z0FFW1j_$;VJk>J~QO2~TIgmMK|!fXSkVtYhS&n%Dv? zc3Lf98=_-7!7km&&oDts3TRfvb)tqB_+yXkcr9d8F+pM$mc*NC=>+S|RFhhE(fMN@ zfo+ya+@LI*bVuYjZBYkU&eQCnDzNlT8OSir)mm8U{P2A30K5U&2nsb+#(3%d1S z6%yHsRzwEU9tuP%V(VE}t<*n2=5x~>`ovg{{j2o#6DxxidC$?Q z?+m**j&EO*K|Q5Tr-lfbNddYcU*Z{n^UFo8K{_y&J{nNNXC`giE0=*QG$nNuRpUt; zC@X}pWUFH|;Hb^IkLS?2O_YE1b|`x6CI+8zE9y|8)Q(rhzZ?%ZY?U@H`@*;))ef|G z8MBtIau$OJF%}4cWm-YA0OaM#hY)qj0(AGOw=)XQYs}4Q1rofIYM%1S4Sd9E5EtBQ zl^C^(ZQnR@6V>z4L^1c`cGL=YtnYNd>Po$VOi^-sh;zYO)>G{Si;u7YhH^f zTkF}Q!8>KBeIp2mYS3TnD^9R}i7th07wrv`%ZTT!Anxilr2qOQW2v@?CTAH78n8)T7&?agAXs=Ivdp0ld`bMGR-A7i}Zfe`R#tOdWsgy91 zV@Xa}RW{oYKZLF7O4yq5{aUq@Y$Iwew>K#FTar|s*sfU)FCp*oqin+rm4~qljtMrCAH1Ze3Ui2uP8P?`cup8sXw7SuYy~~{ zd}_j*m}Cx+KrFw}EC4n}G`$ z>UsU0Sq|rL^7R!)T|cyl<>b%Qyz!2@#<8Y5}j*)#;b zNHkXIJ4E5dXx@Y@;ptr0QUk@Y#Ir80Gw-FaN|N~Xizp5QrFz3e*Z@t~K;xw+Lp>z`meVp2pLD1oT~>C5kE4L^Vkzx%P&oJF z&evrYVUHA#z+@SYuuBs<6mer1ffxD9&`_v7nXup}lEjdOcpFs5O7IW=SPK#06js4G zX8(-f$u0>+4L)bH3PBkO^Zjy;n_hlDR6;d7614Ce+{^w!qxJqYVgL%wq*cn5b&e(T zPc;mCH&RmhZhW`yq>9#PU{J6H!ZKO*1st!r`-KjtO4Ui2^+AD!=FL|oC)FUZCPps8 z^h69l2|sG3DmXIZV=c&K(a&dkhoAksvLipzfiUdEcn&dy$V+w=+o#`Ic{az)Tj`oq zKsw>4rN$d+08u7OtQr8nl0lUCQj|-?A-j_`NNk|k7j#I70?ij;1x*^zZ4Kzw0YS&0 zETAkpbnER@r$00?f1M~}?g4FQUKA~7KKq$;2onmX(wNqz^kOZkdh=5lv}}#Rw3MK2 zng*}SZD1DqAnjwOm}mA^!!7cQW@=;8`F+;JVkNs;RfC? zZuWMaQ6`vnWM4~qP@p;DEr(s{TGbC&<3lHLi+h6_5#XI%1WvaB2yb;67lq#?&)o?{ z39j;1#Y>spwl2$;cUQAtdK(_tzp>f0wHe=`TN3TM=03~@HNV}y6z$&PF6{<%?%eg; z9B3_Z-!deATQJ$<^=_{uby7cn)Z4jv8UH%J#ZuZr=jsJ{!@W1lzGO$-bJkq?@zgUF zwr5wmMXmFOZE*_u^H>($Nezl>U^j3`6=4D)NR%4}R)nNYxEt^D7 z48e_Xn`14FVDpAovU%pBhK-64=2ZzxE%S%mPeb)U(+TqKttl+Y@FLa(cDwd%jXft% zTG|tdkL(ymtm`l z=uF7pZ#~>L)PhcBNIk-$%ThOxQ$+x+l^m(LxuV?G)nO$ZG z4_wZk)Db^j8cr8T+7@w{Z$7`(MEbyRu5p4|u%X-~+(ZJ#wZ90iMo{e;x*`h69{rs4 z@Lo#-p{1OyFeK$bgsklnw1bFN^XG`uFB<$Zk+qPBU7}&BVYV34DE8@RC{1HNU#1Aq5iwdDA2N*o@(SC@5`_(N&i{#CJ{fHYN5N4~CG$Cu{HZk(*hesCE zupLXoGz5H4q>L~NDeY*I0ut-cK}?6uf)|j49HJ5!DUOi26Z%L$1u{AzOF|m+fVYB_ zxVFi^F?y7AhFWOZO89A$<^$0IU10qxkANf{AB-K;BT*~ye)oCEI${?t|D(fZ6Re$B zZhgTuRcjoUsk_s7F&y_wC`Y{AjG`;`!2ND)Nu*uDv#Ga}MY+J_@#<4MbKAguhU$XU zj=C9PFNYo8H7~BDPcwj)s-_!@<-A5tqo(g8OAi1P!pTFT3aa0f!H&Fco>B{z=JDWUh?kNYQZYnPY}os5gbG zooUmLi)a(N@8WTzA9ji>` z?AM&JQ6U^?j+b`_!MLWAKJ~z`>v^N6V;2knzBobD1WnA&BkrOTAvFc z3N@|Eqq~vnkA{<^>{UaFqXK+XNEY&QlEli}Gu+k*N(FTkEGE240dud>VE?#ky#v00 zal-%%$EXf5v%9fnXSB(lpW`8EzuHu0J(0TS0e=FU`ZU73fh8F3he6a8+%1tf>-hmV zVH^|_Kr|}=RN*>8{;FpYf|VPu%P-T=o2w+yQQbIawk8ehvpIsW4RVw(PWFxAK)eem zs;;3=U>;qz)NZkS-rM!%9--boaXg+YUHGU(h=_UtYDUxv@xpwgPO0gB$JP=$LAJ^= zPIhcme(gh?+y>+~sOIbb?H1x65dgZl>kD8|Z{nb^uTk0(;pMD&TnLVSr8B*beG?3+ z!C;N(j>ib*)=W^97tO2h z-ypgAqCR3>qR1GGNTj+KSRqV&a^Fy9jfE2x@M_r|rn?v>_CfDZ0n=Ci5pY1*L32iU-O?tqxUs z0Igz7HBcR9VV;(BjWW(?5b6zF^=HsK;>42z%Kf?8XQ>5?SJG{4TyVw33Zli7sb#U> zM(VqlL(%bU2{P8FBwGtDc1pd5VeUT`XWmc*^u7gx>TUHNis0iaAeVBA9~=Uy^X!fT z9#n9UhLs`v!~~%pu3%EV$U4T|3%Q{Af~40hEl$1bu09tRs^~os5F|h>h#hew3 z_>YUn%V*OFSX^aHP4)t71-cS~Kk*}s`rygXdSU5C5aNWF*H(9V1RDWamWg#j+_6Ro zTI`PW69^fOO`oN$slE|^RF{J-#w{tjeqm%`+0T-3_GSndtL)`>gM*h4(rWzb{W&TF z`rH;yGXtg}3Uo5|291(TQQz%T6$}_$WbpUuF@PY1<1H$Li6qdf0Ll;)qTk!RScRRO($oROqVSvgA zp6=-79mG+UegZ;FhmvUnt&#?eGx4ip+;o zMWiSOUe<(TOqXckN9>S8K6MwlGpw+>po}sY%n}1|B)13-0wr??VwS{r5wc=~EEg_s|0$ zSnwlIGY+8AZTDwM3u2qjzddqF4jwrI`ubXrE9&wix^ob@I?F}xd%xLp1P?M)j}{-D z$Bje@e=B1rIDA>%+vxVr$cknx*t#T+?+afZg1bkeXH}QuXbBlZ1o}?-IOU%*n$yE8EJ$fUT-Ir)*_H9bN5QG?et@Lt_L#nzb6zlACpU$0L#`VePgGCyopAY|u zS+8&}rt4`+k^-oI0VnN4d0Sy7m+|rzF7Nf-(&~@!iDY#KFYXoMuT7U>-akt%H~YW7 zKPbAGspX!=i)?CrRQte`zNmaF(Mmpa!zF!P2a&BUJ_&WF)jIVg<f5p|F>68$| zXP9K2suC`W7bR>0ZYlcHES45#b8t!~34$f=uH<`wjKhnOvU!=SPvW|8S7_O7L%gUR z+hQ%OOf8*Znye*m5;%<{I>Wgy&?`kA;P<{@{@c(f|04+2{|fp4uaN)$3i^4-w=e!1S+w`F|2`bf z^&9Z&pNH)IcA+x8GbZAWb}sh62rmBzv-#`4FpSDXj4F59|L8h(`R*hQmt#feiyO~D|2N@q=09fIWFxr{x)k8Ry|OoF;sC3!o2UgL zA)rJO;7VOD5rZ3q8lRsTsqW(NGr5~@E7$iEowKaBTFK>lT>|1sO&24t@HLaz7mhnf7*!^7Xd z2>xnB{*&^f-$lbC;oyFe@t0I&|w=tO+@JA`zUpp@gE7PCk z0xLR8(Rhu>KG|RQ%|UH1J^_OPFD996cM9S`Rj+Z>1R5j~jlO|$iQWchq~+UG^&Jsu zN%H7^oc$4@db~T_yL)M_bpPOL%aAbTG|N?da4>YRMv2YAu&WumPI;u7nmOR`cw_h8 zBsc9foaeYAs)h+oW#nh0W8D|o$pA_D%d3>LqQ{LneL1_fx+%stVBpFqRpnvZ%QB+Z zhilMJK@E})?ED}oANXbDZ_84qkfWHtbpCHroB@0{;@q ze17rNH`O;5DqG?dhbMCY9j!fcoHT~|nzHo6-)?Z5mdNbxapudX?!r$|%&}wz)1?b$ zMZ>U}->goZF`SphQKr)1hd~BWY^+ovx;_R>uKpatwvArUUOE4!Au~4Wg=u7Lsw`d= zo*EPR74|`z`8&0M&RY@Px`8;xd}7u&R|HBY!}^eKUjZjaVVT0r3Q6B{8w!M#l8NeM zc`N%%AOJv9^}U)~4-jK<#7~3$u#w$0H?~VrB`G4#vZf1iwv%S8cDKMb=|QE!nBzIY ztY4qg0p-djob4_R(0q4IsbJF;>`#7kAH`Y;%kE4JoD!u~tV=9PP!Gy}s_IgWNYLRk z5T;Zs(?GZQh>@^RX|GlTw~zPJ+#4Y57f@E+4sQw{smvwGoB=mT9-J514$#5=kS~V> zn}{nB4*MKS5>w5fqoyJMy?C3GJo6dPN1nb4>w@Q4rB#>HU8m%TAxIAk@|BBzJL;=^ zQk8^$fnNP4fB4kEp{@tR+oV}hQadI?>qgiq4nayG`~gMUHp9x9r-8#fF6hh)+@OUf z#hu80*Jd?xKw0lgGN8r(Q2F!V?vTc}y7-UQ>82-faQD$o6Oa%}-AStIOx}FsPUyD< zC(O9}&gfq!=ioQv;3M-rn*6>J^_}t)L}gs{_zdfz(P=i-;wrbgVH4WmF;;EzaCsZkpCic6vhPz(ADGR3&1&C_EbbWj9wj z{DSOeAvIiCJU%&kVqd88fcim@qz4~2r-bTzC8gE$?AX+PMlO1Fo%p*j8Dt@{_>7#T z!c=s=BVzvTIxF22dL3j^{@97Qf`c%d;?l_a>S%^xhAs|gG}pJ&^6zmF171F%5Y+rr zL=Ogym#OR+h!tMBFTw_(gqks3W^~xQVttBy!1zz5Lk?rBmKRyLCqsa4d>Z#Po6V}5 z@dk$}COz&=wz4(>>n}925ZtEUN{)-xXbuVg zl4Le;Yjo5}v6Oe6jnv2#FH}Gb1e3Ttxe!P*#p; zHTVz=cDBfTfp*Q@AvFD6IArqk%BWs_a*nihh&%X@+4Rr{uR^yyWPeQpu0*b^^Az?H zgmZ6pd7dZuBN9Bg3vqSIi3r=iB@^qR3&0S8C3nf5Of<$R^QP@sn%a1U+1b1|6k2ud zaXq+Z6@M&N28U5f^7q{-bPoGLI$P+$)#z=uOK?Q9U;?govDdNk^eb}w>MH?Xlw#IJ z*L5ki)2kmY&1?rTNF~0z;DeXSXm2k&aY%<$x$*T6Ti}~D=I=|z!t*Yv6GLq*x}cvv z5@y;D@%jlXmZz~pnPUh;4t8|-OgmnED|fGgx_d%nA8%uay#|(fMOo^Ex3gMorqnj) zoQN<|1?}4ENZihwr33p8-l zeuyfnG!Wylp~N`oyDR*7(?)3(LPy!ndvpG?zf|lu;RZ|`u^&6MX~-(oIqT=VbHZ)5 z4OP2Ro|r$%&ka<0W-IKH7;L+C`Q9Gd3_R6RB;Rl%YK8mV7{!#uzQbAfxC}wcdbXuZ zV&1QF+aPs`$rZ4a`mM6k>zK2*F(46w_G0mGd~k> zEvV1tdnq>)iZMNbYdndj7<21lAU zNuCflnz)vvNcla3dfc3xxwpa~E>hl?>=VkM-<0Vm1#Zw}VLNbB;X0<>W8;O2y(mHU zVmM8Q3bfAwjK19+A8^G8C;MV+a_(1#mkqZk4uvdL(Yxx}t(?$n0xFAbdx`;6p&@cW zX}ATk?O>J$#e$b$tgfFbC~i*x&0K&v?QBrS(%d`waLWpro2f^I*7_V_+-oZqVd;};l+!_h>R?%eFs{Mi-40y*dq7hI{MWcq^O+q~n*%6LbkUUcEf`&-4# zt-W^X)cA$O=M`DR;#i*-K94#aKxSyT-6$?_cLcpfcGs||L{1)m2-ks^!0wL=mQv|a z$^d5%SEAut-YbV4!RqTJ0i(zViMX`$qb%Om#clz6QbHfjy4;hKP( zO#_E562}156%1}Nh3dFyC!Q73rBY}pxzn^6=@hN8U1seI z%NnM=4{F3X^{Ous@1uDV+@fka@wYr*v};l+P5Q}wVn9*_d(o);><RHE5aGp}-^*gXkD8Bm2pH!vwW+o39RZi}8%LOXs0Lj4R*swxe>y z+>EXbuQSRf8?LLYN%-i(_a3}D?GkQKl=h40_g%O#$=p%}eBBTx4^hlZ1PyC~ zmSjsFn0Gpd+a|l9S0fX~2ZFvpz}`KzK`B4#1`f+PRt%_jtENDJFS)zXrP$S=5vJ4` zQ>qbO{{V%Fjw011q9}Aw{OTJ;6PX)WbGPFQ{sorFTB&v!gc5pT)hSP)|HXMm4^-q4 zP_c{@JB@-`9-WR7w7f`R^*~2Nt+6OmZa1LHsoFs74eDx$MH9cC5J*k?B=wjZbf`dN?Y?(}jzUaPSd@l%`J*94cB83lFA)}ILp`i{b zREro=#h_-jad;0*B3meuIKD`WwW^+2sUFmbQ*!S|jO|9~C{NmPvCUo}V5U+npjye* zvVFjfFP5$JfkjSG!LqkyTg~2L41hzMB`-z9q+IyIJ-)(}jD3*!N6~yd$gYD+1t(L| zDqW;XGJmDlgh7cZ2L7pN+1w!U?h=X#m@a@i85RTM74FOys8Qy&&qOO9p^0_13Gc;N zf3&jl(WtE>;*;!|+siz!MXv>ztSR;3jI6{f#&S0a@n9M=$+u_(noW0mqhMVK5bZ(M zDLWZsP)pk?f9OuPo@0|u0}{O{VxfqMuTR$Gtqu9ucYHa%RhtI&madOni5^E|AK8$g z%Ff^yq($kfF>%1k`j!^p9yMtm8^aF-l(d~8I~*Np+rH~=lEL3x*~BYz%9wpps7fow z;*C16m$juxhiaSf)#-BT6Q%K`)cH=8$0J_K;d>HaK7rq3w(H;F?(qWA6}Pnmnn+tj z6JB;d)jjNgp+Tde)(O#d?5Kg8OZ z7+8OP@s~IBkJ}A@E9A|}@YgKhzY}Vw`B@o_1oT%I`(L4UmBHy>ZR`W>kfHv>lVkj+ z(Hp<_ z$Ukr4&k>pNU*<*eKW&SD6#xAjYyBVQznOls=)aH2fAACk9{&3;tNM4C{7>_#evipN z4af8s%KsPt&B*@q)Bmgb_??IP6VsS}!?l0lhWJ~c%<_N2e^316ze$9DwXy#T|NX0v zeV`~Z^q*n!UwLhRYg`Ui_J1?-nT}2jF1xc=w%*JXY%_o~LKKAoPQA`}&%n>sNdKl) z!3wfxc*LDuz}uVddwzOG)!abeflAB}39u4-c|?2r3)g*uxOMNt;q=I6b@YhZX1S39 z(L>)MJ))0K=#yd z>Tx`iTUX#7_! z5-ndt@|gyQyM!-@c~gQut!%tMT%PM8>iN8$PZ7NBbC;f{+iv*WZ*Q-YyG*Zd4`mlB zlRVG&4C&qmaKAk4Z-1|vJ5TS6dH<2~WVDE56qIs(^Ul#vPB2J*S8~d5d!k|!d<^de z_wm7-ql>{9&{9w)KZojcYhfp-?&?0<=Q4XBE3tA>q!yfy&t(z>Tdd|Omiq0`<@8~1 zH=Ccw^W|#$s4!jptaTfyI04`7xj{y~+=M1jts_Z8zty}Urm=pT@O>~_i=WhXan2i+7D~1dv9GP#Pp;Y`Ncl3XEDm=rP|6g6KYU*DkJN0_vo-`}lO!-9B34Z#%7WWp%L;kUO9v zm~2c<#mVv{F9}%rh@;WSp`(6ibGHRrCY8(H3698=9JohXKZo;{2fx+~3fM1aGw0dF znuQD{tASra9CludG3G3%84>wieLMWxU{` z$|-y5uES$SuES%Tflxs+gx;t=VyymRcPw}2PlsRP@_xtf^9(>bZ_0ju?DFw=xhj5t zKHUB;Pr&c>blaIg;CVAaM7$Bv%PBf~x1Rfe!bO$sU#a$%{1o4_v-9PDbG)K+O z9HiS2t-t;;4pK}XLNB{Mj)H}7d+!ct8P#eU^9y9H!{9ms&E6@n&}HhpYGBgiAW>^$ zMD#WYiVx5*2CN*Ej!_S^V$gCl1Pm;w0!IMIkcR?VQ8+pTRe`(+8vXX9g%ElA&jK0u z&p~LW=6w{|_*(TR4ktNM>Op~ck-WK35T!vvLfkdoyOeP03RCug1{O#UU0~1LTOjVx zz(AO?jaV;GV?;8&l01P+Zc8JEE$tEP!!Wz%*dUmtn`v3 zo@m32FY86(tzk+Pd?VpG+a>gdRrRQ139mq;g@h zvJMbBnCC;IgjB(Ope1KbL?5MLGr^(efg}VA{xqSpP|f{?+_`_yhi6-?^n0ulLC0sR z<{PQ8HPm*{XLYQ=Tt&Po9jnHl%8rebAe<0ufil;g0M!CDLj4u6R>&{jt2!4gZBpO3W$72u$OEkzNuI9klJUP$Gsria9SIi%_{chmC?O;5L7E;ACC1zet`zPcN zLqn}fBpB^hkI|-5y7yceGxo{Q*|B;LuBW!YLz)D1xMyS@FR21O6d2t|CaR(X zCpv@f*p}=UWnQ`+2t^18vlGeC;R-aP-5kLSp@mYqLAt?~S-7$oo>9hh<@TPMfRqHw zJv6Yj5u<}oQm>>I5J^+X;0yzbK?<&-Zp>P96TeM^M_zEARdhy3^lBNpl7Os;KFa!F zWQqv)eEsHGN9EQ`JJR<>^m>@kPH(3lbpFTB-ck@~0$32OGy3L4eGH}k+0nw?0Kr@! zXm)iKza53v@)U45;kbxo13R4Q5J)jP0r|(^tA^_g&tGWsVn&aA8jgVIaJ{ z-3FYpS^FGt>>C{6&TMJ$bvXl7KYHD6qIocl^`tP*U6xK)X3$(#C?iU&^@XfYHnL5|TR$=#84fK5qi|neTP&@FL20q1+CvZ(gMi z%(#N?q6U{s(PW~WN!%fX!pOs$M2<)I2UJY~P=F4YZ{W~h$s{lrc!X8G@4?2C_hxF7 zH1ExxK|DdlBN9!jXqjwS0+$&i(U?dsP5IX#tRwu6TVOs@=ywb|K!xs*gaTN`@1;2~rR=XvYO!d`CI=fzaO&TE= z&H-N9@2=?xIMP;dL)3)mi45Q7v1B9htdWZ}l zeWA}+prCM>E} z8DQ{N-P4O8Ro22ldpxI2jAZ}Odm2tZn^|wtyn;ZNe?K9=emR(7ss^I7{7o6pdj_or z&6ws+3?=$*%gpt1qCSHxDEm)FZA@k3SKdu2ojSZqhG5Blq7n&kdRg5yXXUnbMnggGjDbA#C2Hkf2Bwe=*8 zHkdQU0=sjUgtk|>vNL(bX@X)kvOP5I2NZ)wm?urO;qqWQnMWpy*^2Y+>bdC= z2&(r-C~((2!H=`SD3Qp=$~Q4Mj3D%IttTQiPHIv|YjC8uEX4^`^4Au67qtu-N?0O z+mlznf?7`;TfvMio2|&ylHUdX*)$X$7ZEB5P4g-gn4_|$d|KkV=diurrH^`fYr(FqR)J!)tRDh7yy$#9C}v) zuyTK^LoXIr0g)K}AT{y6v2^wiF}8+1cT7XX#Akf=YQx_7Lx2Og+K{0I9UTzef)GS{ zErT*wMQ^G|SR4ox5mt~&lS4@Fz!4BQ2D-CyG6QM#Xf zdp#RGj%E!2v1G%j*9*hiXLU!H_}FOigqc98pA3Um(z5bg;LBZU@tGGmRn<(PGgsYH zoHnMt!tqOBF6@TmsnMZ3oG^6kq>o6QiG}cGri1<95zV@%Dwi0;S1I!bK$GbV*iWD4yeGQqVaGI!Qi8rA@$JRReVx4|w%}_z(}6r0Y~$OA zZ(anBOkQ;Us=R05;AU;s##lX#``&pj+Hw$F$!>GVG^_7L$Ih1p+iD}gN-2}JMu+Ex zP#NBiU>0b-N zAw;5v8{Q!NHm(y*#ASp1eDZayYi-uHAUAC#xzf!gaB=6oE@Y?H|Ln{VmZ|Ym zSZc2H{a8EabKlw^gPD=-=-Zp7NTh|&wbOW~eQ`4KmzoC>V#;x6I zXY0dko!m7mj_RW}m74E}7fWjl3vO-0LKR#aL=z<0FK#I!mS;lIID^*gYtmF@LcD4^ z%pWJm+;qa1n}uhGALx~24jjLnY?_aOX1a0hLv%7N5q9=UTSrs{nv=(?gz}aUaEgb& z(B`b?(g5TvVtwTnYN%X;jN^Rntd)Q-1jozAnc-!TA3{_En^@RfCShDAOkUZlm%>5) z#ZEn|0)pLAaUkm08cy2LL*f?=!+Wd_Z9fJgVsmYtA_Hb7w_)fGn^cr&4fWU^WGeek zqsFjh4_hY!Cmb({!45chVPuxzD#1-krQyCnY0wb24#tT;dgkr&D)2R;TT!3dx^VmJ zE|^@t7vYH3;Q|X&giItD%w-=sp1-StQC(o!FI^s_v~7F{o8h;5sS4i>K1aVztrO2d z5L37;$XCWzk-(&wFcjW*4C1>s`M7K8(qR;ox@Us$0Z%W&fWkK1EfrLB6IIV(%6}{; zSEe_e!8Hh2`|xbGU1iN>s#rX?{(kCJ9fOzcJeftOdD})36A35??F%iwsit6_crc!t z$|JLL!(r{PEdlKawGyU=x`W@obj$~eP85hi11mi-pU)@`r#%fr>k+pDduUq#}Q8%U2V~BM`SPku@rFd zc^FVXy?)tNY+(kKmDrRheFBnuUn@y3p}HAND06U_yBvoP*}~cgEI5SPIJ&0{+^&2`~i{qWtZYW6!xI}{U5qwOj=&_p?Q;Mm9C}5c{71w8ZhdwQvM-j^GWPi=4 z?hBJ)Wt(5o>GY_nP?xT9=OVf1C|io-w{!NjIp_4Ebg_=^)y1z3N;nw1SPS$sI?LhO zL1^*-JdI-Iqj=hp(z2#=g&!7__OuN>8?c7=|c#CCO-xu=*yxf z_Jw~d-jBeYp;iLUs%1eaktY63e9IQ zmUKdxOwP$}Az8OS;`;w{J zvlW-m2r>~3BLNDTt{aDwp&3MEx;sdaFVtkB);o%I3#66jnl3K}&`c6V%yHVsf@7`w zu{!Uw>#1qTVG7>ete&20; zi6Zr4VMk|P4kJ!V7G@=Swyv3_|2N80b!hb;1Cyp>J8cmj3$}Bl3_-o8m6yi5agd`G268VqnVFK>gx6iPBm>a$CZe@Aonwa z27;!6^V`Z7tYI+{hUQzs%L-%8d9oxA&MR+~cG()Slm@35(LJ$)(>{HYz@lrTb&wCb z2T475OH5gl_2qF|%Vc}~pMlL6>EPoN+IQf;)S0w0m3RuBP@O6SzSz0m zAT@k3$O*WFyF>7g=B}YS^6P&VYl0Qp<*nGV`w&!lc18{DqD7&R$FA>d9mI{yHR1{n zWV5R^E$DjpRn_-Ost~Vem|%I77wV*gB0E+D~J}?EXb9&kYrj=O`75DZy*u90Ay%>k2JZBd4 zxW4QP0=cmmPsEJ}fKxj;4l$8-qnp0cwRWIN1lx2|V(r7VKERDj z;OprOQXnV%I;feq>dO5k{UyiD<0;r6S>wggAM#rZ!JsmW@~gFk<@X0O>fIIuX}IMC zpiEy!XwlpsN5J3m2*3Cml`t#XE=3^iUG+ zYHKK(rIV^2t347E{`B?J46j_LDe}nCnq?-E2_##`qicsZL3LB0N~L3FJLo#s)3Q{n zmCBOiba0l$vN@RbC(pbr73joAS#!IUr+9`}YrPBDX`l&}2Ims4He%qN#w7CnRA7S! z4uTJI--YayNWgY#ob39nUo<{505GxB2hO`QVch8iwcc#-vG2nSLbym!tWT$*z1^+g z25#`5(6T;pF-Rh9hM?o<{B%HEVLx9V3|R+BBV9WC+Yykp;26I)|?4AS*a~ z-|7F96JwpWf)RmF7w@4KmqaDEV0wtq^#f1G1<7B#Xl?A^2o4un$}{%&abcDi`=8)0 zeJ;Ur_qNS}QL|cMo2Ek>zbO{+1m3CxU(*MepdGS%otn}mq?~h$9ASvaL@A;3^*z4M z&I`~py&B*-E|0!iL39XUI4*+8T}679)RsG*7Zt(G6TQsn<|6pz9Duq5ZEgX?j}Xf6 z7PunC3`0(bt7muSr`L}gJH9So4VAG|_3Ll}oS5JBPR(X&Fe-Oiah~E-gi}`i2JqJp zUUwwPrtuX&c}ier_aie|fVNck#a7ac58f}}4_+2Qmk5r?e;Zq6Yr+k)RT|t=>7fxr z$V@l}O)F#RCk4gfNX(L31|=}=%rPn6u#{YjG)g-X3DDxr?&bDy*>;EM2>+5pJ4{`W z*)I^`1bZnw1c|dW|tT+ zgdcgfGl5j+@pd=Yr}yso0Pr@5ma=3%Z&)XKyiU6M<|IyZa``wGkf`Os0W-{aeKFnE zr`O4^jsA8w*4K71v7O>0(I7!CkbQz-9L2x=1pO35= z?2v90yP38n9ky8juln-DzH0*L?pQ#47RQ`)rLJ@gLJXp&n3U6%n&4J=hNZGb_0vOe zhNFMBzh^wtrX~GUAs?zcEs)r#KVfj~INU}*J0JfSxg3$pkhi0KsN;QQPnT&;DPt)| zrXPlqwkCwn`H^wqlk3?e)@+g1cqWKPDh$_sL+Wc|{T!ZTj%igmI~80Kxd_5MVA<&9 z5^_pChl(?m;*i(6MScr$dE%6S!N=11;f9!baI~0QB+84u{=}8ad1DCHI|XiA!~I$@ zlaRQ2xxtT-UG;VA2tv~QOIM5X>hF)+hy1+5F@c{2S3Yn>$&fyh8WA7XtH#xT#I4ki zvxh5SQQtSzuyQ`NXMZCF`&2kMoT4x0&=%$)_cokj#KT#@KMH&0|IrBEi@$RxX0%j7 z&T534|5|74A|rVwk#+=%LdhQD0Sa=+K4mtPfq+1U9yYHj&UycbNMR!UI+8g-w4Cl) z;rc_{hA17PIPa~dtjTq~cZOnSf}R}n0Pg;J*c6{5n|C}D?VQ(BA!{!`-WXST5%#n0 zqXDiOt?b~}{6MmG^)U{Oy^uIcF}@LeM%i4WwFu&ZAZ&o&{rpjyMVjy2D@+5M`EwKdIQI3p*ANy7me7ql~IAA>s#6kkl zQH)9O77K3+F~ou!ZW)uGhSwTYhTIsul*IFmKx0&HuFPx-?mjWk5`QU3<7q0Pj z{{nJKbAld%n*r_s!`+2;g-MS%jz)&0M(Lb=c6xf;1re3V)cg_0>sOrT_E=hzI^N~J zS>{KZMEo{ZW_`*>+|&k7H{7m=FtRbkSCJUCxfH$w=c`?GnpNS9pgOIkW~CuXLipA= zlw&u7F~j}IF-giXZE?zCmt7o5pWSNZDxT=g-Dt{?vle2?nbESizG8?Zr~$5VVecZ@ z@E@)Xfqg=4Op^EeV@sbO->*hk+%i(;AM)vU-;aec*y(wFdkK-ogY65U!H_Fh*cvsl z59=$QYrDpt%T0=VuAW9xI9MF?>EB~AQ;)K^k)MW*&>*EP(xZdrMw6>!cGXh#r3GKG zV=Af$r1$)A_v)t7S_)FW^3`#ne|Kd-*hNuglk2W!h)kk98)8hC9)w>=+aFLz3E3Qf zk%sxIwrlngzP}JHq4(Ab8i#6+?84wVIe0eeN3wyKTJ>+| z=Jj8~3+=S`sjNR@=JuDCUdkkV7~4Q@sww~_%96J+{?SscvE7?g>tE<uSti_Z(EuCMr`_D4)|4akp$dx{_bd8t{;$^y3H}LGk2BO2PMC zF_R)_uLI?^1(`LR^`-Bq%0sl%6J5@8_{T%pyjTTS4-vV}yZ9f?oQryRmQO^C1ta!;jt%*mg&OV#JlB3P-AEnhS$TFPrus7Ie!{3@ny_q>jXA6WRL zLJaIV<|DMm3GJekxG8!*1#RTa2hyqZSrG*Evl}#L1r36Ou6J(t)6CCkzsyDhLyJ> zcm19+G6Gh9nJT_N2J<1!KFDj%7FT2g-ks^ z3FzhyE2qB;=sWe;dlXgUA??N)@5RO!IedF9N8a5-N!HB($$2?*RCq`YwG66i{Ox$NGc}vlCq~r$IS7BDU6Nrk`le!+w+JE~)0jb1pgMPd7bSux#22jMFSjPe zQ-TB|ne8%}M}~~8Sy^gr187|n8qx-q4%nj};B`MvQb6x9F#r6Wz)n$(P{JRf25TjJVJBe2j1ynwTzJw`Oy8n;aODVDy_!8L=IFPNUpsH|~-xLGx$0UZ7=* z86;?i)KC>dYiWl?uyq)k>H6Kk)f2;IGe<4D@=URi1`O=|X%kZ=b9S1D&u3}<<1iS# zG81trpY%tAMHx}vhNz3_*>ixQ`hzDD3VN->Si?ImavSqGAcD(?4kG5T_`Fg@h_(_N zfeq~Rya&4*$JzC9g>?r2Mq1k7V3Mpd)3Ak|d#YhG+%^mZB^C#QZmLyy0hvsLt?=a$ zQNd*xqFQ6V^$iKTvWBP?hSLrE(d4A$O|W;es~(^sM)hp&Nxq2P;sty^^8EY^H*f|y zQ1QAVgI{rrPG;z;}#8-nvuZi|LdUe^1Euz;^Xn<)c&lw4~kWLo@6h z;MTF@kT=a!{qFJIcBsi^h}`oHxWYz^=+CzMzl@yvzbI9P@vpbLY!vse7R4eS z*}YDr<4bM2)$%`E6eIlBqWC^#i30ox?S|4+HC`g8&?Px94nnyKsXjSbTM22K*VSX% zdgo`0;yhOA0Sd;4h^|Uy)R?LRPoKE!NvDH8E7;7#-d|-R(};p0*!}Kz6zG1HiG0EM zRVMQJP$Z=Xqne)-;m@AHKT!z%I~^j^PaWdV>mQjL@OSERe~$j=x?HAzqI~&ZGE;`> z4?^X?OE~+RJ^x)*F4G?p=>EPR|Fxw5ttyx44?5rfF8TTIRk=S6_p{&auN(ZO%KbUh zU)OK9`}^JSvtZS4-q0UZx&I}e$^VHcH&W(TrVNSj{}$!K{SxI${;4RJ>7S;9{=Fmj zA6K&fEl-Y-ljEvnKWs$^F20X@xkSrgD>Zge50$#%8Bq`MdZZa&%@XJa!Ia2lf1c^h$2r+Sz< z4gNE%b8$Ses!Hz8ATslWN;<<&oyta|db-D(@D(EDLc3MVrzo#ny-x0)DOa}?Cs2i2 znae*zhrg0m|Nk>h=C3Lix@O2mGX4T+FpsWYrvl8?Pn*m167aJ4zX9}nO0zP|Gz<5v zg>z2wI4f^#dsw)*aG2P@Jaw94i8%~DqB^-}AA*pfM&xrGx6hO11TT7C^gRX?f(>le z?$TD>hc&+LKFgl?{I`s)l}8Y#bv&0pu{iS|vIPITPO3j7$}s&*>ic>9ue0>8GFSiO zTk7uxWX^vFkeUBw-V^`Rw)jUS$}s=Im;Sp@^EZqByO7NM2RHHW`|;muf&O+f|F0~0 z=6{+?^?OMEX*j0ejQ1NP|C}k)Z?pZ0yT6BIj-MOi|0{X<57`iZ3uFF|Fgfa1q6`V_ z|Hfp@pO_p(jg0zdXUktXZGUTAHio}mldc(OI$G5@?D5`<)klXwap^87P$2!zD5rfu z>4Lt?E*GQ`16Ob#Z{GbV>$Ffx&o5#Z@-!Vh4f~UqEOf&Mc7|H7C;$@g@FcH~cVE1I zXyOJy^&n>R5xhBtP8B+DQ&g}9Fy-@FV69yaZ6f+Sn?69k3gHDMjxMVJ?)J54#Sf!} zTGSITce19>5|v~h`Pn72)@XQSL#%uzAZ!$$0v7*6hXcO-h$~T8JeJc9yBz>RC8(`@ z8q^zLw)X(fah*}>q`5jEvYhWC6+8eNO(6u|Tr)W*2)cugcr7QHzgW7Vk_4BdHb8Z` zQq7!K^Fyu_@dj3mn}{jAdjp*&lhuzhXoU`a3#M?7vFdV5rH`dU+`64_JK{P^_Ss3u zfUm~4E+T8%+mML!zv2lT-Q zZXr~&8BU&Q=gcxu06172f|WQ7Yt}AA^Ku_M(kz9^P|3Gc!s;@TH%j&TZvKlI(7@eG zG2Cv@2Qfwj95_tzIn!)ggM15L&HyqBCAEU;J0bEA?;jYSZYJqV&OfOAz!0bqJ{*p8PFav+u5lhq6Q3u zYW$;k7zbLwj!X2*BMs47O0XSfZ0h5SkaLVza4O0ej)42QM0XpvqpnG9k*C7b?VwhR z2HBOi%Vd-RBm(CiBq6H5r;KPkX~91!d3OYjn7BTJZNcOJIgH4z74#O|n%0vk`Q~3PgupH0`3gDSAYw<2Wyii9zukGj+ z&nXG22odtVSzPD(**2IL+uX2^y6_TAD>B&PYEB`^TMIy0eeloiLoA`1huD;WSY66l z@U!j)?mZWpTYpYwvzZO6kMUY646vm)OqV50TR|Ys9^p{BDS9FGZE8;%lb+O2{e>2}6ONWdDu(vuv6v}7Z|!FX&- zvpW~>Jx&wG%%${Um!aKcODysh8*s6IK%3uq4+PL|i#hVvoq+oS+=I56(rDOha#X-K zo|x1d#R>fQjqAL1wL8_!QDUG^jlMQ&3J025?XKsB4694|Pw6GX`e*h&yE_!>2+(NjZj;ZE+C^TtOB=E|D81CJ*_qcr+P zfQ22H@bngz*D1Fi-ZTG8&&P~8`MCKR28dP6%_&6mX+(It7oZK-3iR)6hsE4(HI9xB zLEqH(eV~^pDaI zIm(;K=ItW*-B6OeiMvauVSUZ8Sa{P{mnv{tt!;$~ z!FGYbqVT_ehZF815-6c4!i?tg^f_s2XK`6`dbZBfsSm8MiFG^0InxkjqX2~z`iUJDS<~2Hk&(k>I(}qy~G+d}C z?SQ&Q5j`tg)p03kKR8+LUJ?a!V#9{pNhDyfs>ASMc%jG|DCpwm`Kmw6Q6CzcGqt)D z58dzZ6*r0vZ2G>QkX58^>w7J=8#S}$KyokcF=>n+JcU#>g ziF*)`?122Q82Cd-*jLJ+APj)ko2LCS0}{dv;2OQ1eTU_2C`cM1(qD?SWso2^>HrP`)<#opFA? z0Bk*-rIs@g)N~}or6BISEechM(vs_~HBxgv)+9*Td+RC-k-D8KIHV>Mo(%>L&|(?% zbEqXLNEUsda!6>UX>Q39hFC+dUFHq3PX!?diLCVQd80!!84ZUo3-?@E7hEz}w|16N`mk;)C&ePfPaQQ;^vmRqzBjD%n`JcTb0qbRT=>_q& zqmdr;JeV&T2)po&5oh>{+#D`+Yu(HDU@T8aeH2uPBGSs5oms&#&zNKnkKZsGN#szc zYxm6wS2MNwJ9QWAXz@NxA3A1uex*fmEo7L5a$s|N7bLS109;iE8Vu3jwWnf8Y4KGq zIh%VX8f+dx$S$j|IJbXlYK8Q@*_t(}PA;k!*Ef=#Y5N+*y&vhxe6lX-u$!R9-rI|@ zg&ghmvb-(vZE7gSi(iYcIKP~IT`}wuK$nqJcf*2v5~b>wnUcF(xjG0dvSr& z1g=<9t$1vnb&%dol;@kyg=68^u4f|r&EEMgG%IE6PP!R9OkFv*t0%Qg;&8LQcYPS& zLjTMaZ&}#-#Z34hq`VFftSyM7_Y@}SN3UIqNc)KK8$2|_RtJwKq!!(9HE@@cfb!S^ z*2}U}^*BAauUooMD^NPd0_A)g*p>euRdM4dx3{cmh9PmAw>8q87H!i|X zr66R>W##oL_Pv{WXO=>AYkw%0si!_xP213h)8xArt%p?`$d#nPy;nn~4gJsJOI8cC zx~NlL5kI(KN{wgd8@?{iQ#pNiQR-m3>Z>UtK{q|)ix=Abu+#w`@5*OqY*#H{Eq1s~Uub7`*PYtW2u7iGn>vcP z7#4dQk#lo|!=daJZzE9dBUkxZ&n9!n$6-Tvk*8l?4#mKq)lyparjUue7r6Dp9|_SYBpLc6bUd`VIGG2)b-}N4FlLed5uOj4u|CcdEAmZ~aE}iKpU|*bG!5 z8-&>AinxVQvbkdlzGKY7V0R9v1hwkxw?$gC3%3>2eK0#Nq2@M} zt26FHy*A=p8bbj6d{0=Xsm>}1Dh#N4w`2cN(A$BpYL0ucCEluMw{!EixN0o3o?A6a z)8v`iv@yJp}6sATYds+$bOUP~wP_&CqWH zFUHj8PnmaSVlLL{Ze+w?oF=wM`%yi9a7t`o6$Y9IU3cY_mqwBZ8)wmX!2Q};bXj~h z3{JARte--2(?rJEI)S>Yt8w5WVY$jEP1~jRLWtyj3O~NOdeG&b@P^4ZJLOoM5aLSN)7rvVr zsOJ5Z(CJ~;l42tfb^j2Sz25ioE(*y_MrdJrGNdf%qq8fCfJIY+5`4fFJ+R-~bWPZ6 zJoiOTrItAHSI-Eg>}%ScRjQmmIDR}w*12!IUm24=M7`FNH9c?`mHe1?ji;ag*uap0 zCQctw7rdD~zXx!6)6^7@^qH!%3WBCQ1aozw5PBgK{{*2NIXFY+!l4Eq2~XV*64)Vo zKisX&iiUHo^Z8uhjMmgCh68)Uv5vRsrNHt9GkJVz~$okuDV?%j`!r<^fX z_fNRr%){_}20Et;^kV-X_WmrYiR}v?MRmK~DyXQ4C}50sG}-Dfav zFwx~Mcb4{smiJk$Uf>#>W^?8CFB?mP_!Ml#Yz0s^m3Zt2|3B5UiFPTxE7rz`HTHX4 z3gHc$z4MN{81D3Hj89gQ4CYyAjkw5#>>TA}44mUXd_vdVI+^~Evw?odNtv4Qto?jO5IT5N#of7)^T^ra#WX>!C@ss^SN26&CGJ!W9f@Iw*`C^2-Wnh2#{OcD z#osY5Ji~l(vpzQ~Ys+`>8Ld)C?}OGILpSdJt!tkR^+^}hKfk;Fa96MYowqTUfZ^$T zNeySL4l%E@Zh0#@f1Mcyb}t<2joJ1(Z#w^<3YSn?k){j$YejL+;YFjq?{`Y4{;=sy zmm8Z&qkU(ivkqA+5)!uYolgj)Anqk%j(OG4@ z>zJvLuTX-h;qi&(Iq_3I@d;M_qfngW9bFytUQxQ9Yv4dIQWR5`l9z=uRPmR*=84n`z&;B zJ-|K=K7nRi=JezF}P4 z*OviIlfp>7HIJQ-B6<6~dADThbHa^1ZdblqTL19_G+SsL^X7+4dxuWo%{|uSb5#=i zrOj+7PKFRdCDpd%vVJABi@n-fGbwx+eKkGFz*G@y)-2OWAxIEkppF~20w%7fST16T z1s3hu32{#XvY$i|_7X_1J{^y5D@Sp=$_Aw6{kUSDyZrv)v*df{nvZw1;yXJ}DC_6v zs9p5tYdLztxozsX+K-3twqGjI@ke+0U%zP^{UB$=_{(^?QpWpo*1 zGn?00Vo#9AQa!{kaGu6WFnolz&wTaHE^6|r;+f5vVahXsb-lVPKh{>hT{zGEEF~i= zu{(cC~)Sy^{Xm)7PSe&NEFNk(fVLkain&eeC`?rTnmG9M`Negjr6otRyl5|3Ku zH8$5?vx=#I-uUBTM&yaNV#4S7Q!3>Gh!PSn{&8X)N^)!~w|%`@Y1Ml*<9I^f=-J+k z)jN}AL2x}`3FX@B838>+66DUKehr`VT~cscO><@$v|RO-c2QwEk#GK56Hm(7iF)mt znh|D96p1q5o#t^miRr!9e5-Qker4~$d&e-wNhRq9(M2Kn)`;*J>b!<31{0NF<@RoK zOyM~+wtDW~6NOU&<>V@FpVQF%8dE$<{2z6`_hkVc=g;z*{MhUJUCfK_Sm0eEiEeW} zqim3!{!;GQUMm+P+@aaNoKA7$7Xl&SSJL0l+Q_rZb!PRmI*b3Sshl{Otnc58IP7U3 zXV=u1l7zN7N_tCt&E*Fx9o3flm3I7+RCGd1=*Oo*<=svnWQlKP-sMayoHrSzY>G zpL=d&i;dXAzdMd61SM6CZaL)L$$S%ny%^1N{L6iXnpN(>Un^IqOfd%HfZcm(prGE8 z7iW=1y6O$2INEt*(RsUk*u@mpsGNTcoy+qjuMs64G=9E>ROIt0G%3{LRZRF-d3VU{ zYA*@zWQHEvaeZu=;&R_}MvE+kk|dl@DC|Y-o8tAJ{4_|Bof2#=KAFSe4+CvkuQqK9 zW!ePPJadv2c{Jypyup?GMva#64>^OM&_ueP+{$;8z(A3g3fbXdOV7kaB}+bTyLdKS zdi7NP+G~Ay3j1Oe{&6DjJ;2Y;MWEuJq(QgtnA`!KG8REldz;RaW?ThSE?8%XKL z9vuhdl}|JWSGuv{1TFLq^&hWt2SP?DtC6;s2vr@&KI3-OEcv7N)WtpAPeFt!#K>W! z=sWvNMVV>;zcT#)H|iXWeO#?-EW=7Q0GL8!VxLX(RF1J&wrRp8=V0$ z@77JP@8_ISXs8aOHSOl+@Hp%+g*QarD18Swr+@OSYrVJJeO^5KVzlt2iT&@Niq!H7 z84HCbu37{S$4q+^?Q+h2i@i0`Zy*$U!fFG*d-kg;WDa~p{_odI3B0@pLQ5*6n90JC zs67Gw30Yhx(VX_YITVCOpxcgRopqk53|&Imhn&zsm?1b9Q_*Tm(-X22WHfYUJn1=P z{OSn>9#=hY`FcUem@f-@f~MOqp2-OHZVZCO^o`&g&)K#p;4`MszP z$*n!jJWKO|ygHIy&(auWSLX4{qq%lMcGrofzx!@@#&|(e<%?#*P}|ATfEiuMA#+i> zb?krfkKiZMWe=WmRIs}-DKSE3!qj-j>luf!@q4h^dpiw98q`IeGx@3brEcrv{k`8A z$Nr$Ucw z-(6U0+NT{hdgbwuQi596wm0Re#D^I3lCF4nCf`DOfRLGI$eK5f{9BE4J%AtjD*kLp zBE|mdi%xaJy8}1$zK--ycy7%Ve?V6eQTZaqR z`E-RY#|-&QtSz^V4~|OWZ-!OjG*%iS<+T#qZB|n#QC`-DIo3ilaLRAkZ(TiGexAzw zFnTIAeCuf8v_4w>=vb6S-ojOK2`@=EXW=R(Io7|q|37+tC3Y6SQ%uG_Xy{}M{U5w8 zguba;uZkFLs60b0JB_to^~^p2hz7t!6DoNo7U-t7_gIU!*gtpd6y(cM6;#Q!HshnL zmlGN1Vj|Q7e;drv+3V7fv^*pZ(Q;08)C1UBE@scR93m;d%12o`R86DpVwl*-prO4Y z{liefZ6>NVnf+3f9+U9^a8T95BU675Ta^00Vj(}m8Z=uhnP;)6f9R(8+sK@CKABty zpSe`U^dJ7XZRvx$L#@Ors-9Mne3^x_7P< zN$%Tz8U1~J$GbB7yjtaL*;iu*-uc9g_I(_Do8v$K=@YicnxX~6Lsv-lN*ken>A)_> ze%0)n?c+?RhL^iW3`-Z<<7k?>F)jTJO=&Of-W&0U&!=0EUfns;IkBn(xxOcbXEK?W z_B##^jC$E|PZUdkwKjf-HSkn?U5zcbrG@|@z3EoQWKQ$QUqcbpmcDO;5Y2^!3TjGSY2!lbmdo>r*=uJ9C@T=F5)iTRbKlA2HLn{>*UA3d@Fv#NDa4F zlp_3yRY0#4w##9BukkoJEexv>MRTW|Vl@7M! zBG&w{B0XV9>24xIGi(Mrqn0bkWgf9I%TmbY>AGDMv-Q(xof${1D86%D?r@n>%tiTB z%Kjsi=24hU0(qn0eR^QlZx43UrwpPMcvS=-sQS9_h!_-)mX}~=xrI|NV-3#oS!5nz zl9-T(emiTA#Gj4=w)^W!3J$f0kiQ&+l-}Ky zXMi8~T$d+dF9Y~(2TLcQJ)5AVI;(YSZ$7c<%SHnB)X|oqo)C4Vl z==X)Ch5@RNvjplWQ@A@Zpxfjr>t|3T^getJ8vfn8op2+ZWCnqOkGL8raN2h6}CD?kwnUkZbPO zMJc}M?`28cz9e-GEF|enD4?*&cf{_#)v)kU?#*{Hk>19Y)QcUpmIuqbNN%y$x?%SM z2XNSdkB{;|q+aK`A`0TzH$oreHrzG8o{BW$0C;O<{=#zxg|YUbU70g4CiP?P!YLL1JkyYirY{^B03eHJ=C@cSoHNP3sh_j1QQ+|mU{^z;HE}s-g zqM*PpB>1M4v%HEb3n0!~w&4R_qjP8sAHPczGn z8?0qv#X_5$E|Zy+_Q^YLhd3U5Iz6{{Z8k9Y6w%bCmQ&d$^i2;Rj>+MRBHG0`De7jeW}WU3cZ_FUt*Q-A zSm}MQ^aRep|h5bG3_Y!N3PK?Sgb^_VS0gGKDWSouO_12li@m4-9>!av@? zsHNGIY7;Nq$$0mwuJYT-2H~|Qr3zQcl&MsG1Mz{Qx6aEqQ>>rzMQz6AH~+|3e)DbW zhWX2@g0=#O=4bX+AB1GqMCqG%oan5y0yx?Rd}>AXfPEkA2nfiEjPo-xBtNb`SwzIy~7Zn zGT(3aRjV|2IMILJacq+y(zG5XX?`lGv)D~>mGZ)idZ=tA1r)DpmpzgrVoQ|2>qdc3 zgSklsa1fCUe@pF?4}^O?;bcTMly0`Y;5KZb^Lu_ou2%qzTM%u&r(r<~-Ex~Ydn*P| zURHRmfoMd^3iQ`KJv`Tm@9|lZ?0&FP>7)7*EmlP zyQEK8)6%TMdp2B?|9!MxZ*&Jm_RaUf6Nj%?RU+^^g7)BKvQO9#*-JTXS9W54xx-IblkCa@go~x_n=^}{ELr-*)Bt&fusWyYR^v&9ezzm2pzsT%x8D4Zm%$H$j*XJxdgMiq=y)n8IPqc=rp3z~uZJK{n|OGgo%ET6KdqouEvJw)PEEJ)@dElzr1U*SUKxO5o@`=+`er zL@y))m8JD^xuHb#6NExxuN>CM{FDSr{*guJ9>yaNuOgzz?U3|V>$p$wU`2Z%tm6q@ zwr)`cy-(b_hG)29itIlVYHvkPe;yk|ro!c!@Nm9>4vdb6Z3~AS;;{xg)H&@8uHUm? zuul8!P*`NyFWRe<#+?{(#hw&IJj!cD4o)|W$^r-oHn}8~yw+c@@(|%^x#_tQe7@|d z7PWw6J?MSadFa{mkspPIA0eJT!2%O67IE2kZcpO z@9y~8*bHvA$u1~n^}&v(>2~g!4!~+MnrPS5TQeqe2>f_Y;D0{idTC+Sh(r1JNIzll zAfafLTz?^i6>OW5xI%7!Ia(YIc&BbkJccDv8IxjgRdqe^2Az)`EV>QrTQ67fhP>hIcWLZR(9g>*!h`^N^(P9b%&$w)i=v7%6hU=|H z2s5IL{=4vuRduFPpRL>J5Tby=em7^T4sBQi?ukOq%%}gY=%8=v95>V7*xlJ|cMQAG z--M-?A}anXDY4#cWm3Wb>Y0Vh-+^lsM&K}93kb5MI@umlaQRcjMXOx@bg1ir2khYk zF%HoU?Q|67^AHliqjchKMD=~-Z=MwS@OD^U<@|a>W&$lIoiib^RRm-<0T}=UKw;zQ z4ZQ@6w{2OC2I5HJy)zBi6X2Yl(~+g9N3LYMGqm7CSc5eMJ_X!g#IotUYwPP@>+qR) zpNW&MrPeuAxhCv-aaDKm${WN*YjJNn?qUg-J?Kq@%Pkwug1J0}utnSJCgy0B0!c07 zC_A?l2MMUsA?YBvMU+171N^o%PN@FV65I1@vmVr6p%abPB?lN{_8CYs#Nue)&d$v~;b!ZFPjsAnNHxL41o<0p3D z4V-B`_3kdmyVrQI?SW#(0Jy&do+yBCWruGrHr>((Yw!#mjWvG9^$h)Ij=sOL~6&#n`NaFZ}vVEQ54N7d^21wL(*Z>H-!&X*hSQRA}3?m%sBg zs;Bn!53kUb#=*vJ_$r@@knNN=o$AxG=No-G9X4^nBOJ^X^}tPGCc#wE0AwCvP^rM+ z=P`iee&c|+r`T!}_H77t2;#JIqrEhOSjAJ6_==X3giZoro}wb9oQ*kxeMJO5ufq!3 z`4|X^)6I$43lSf$uHFd(UY!ARXmwhOg&F+?5=E=_E`Vk-Qp!U9Dp}_+^_-o3uDWxw z%^Q%<$Y zBdJ^~I8J1=}!(t zl=U@^8h%XZ?=~jcqkHBtN;RSR<@$&wS6O>e#n;*ltXz4h@7Y1Ak)n)vR7cyIUwSin z-Es7^F4#=&&2c)bIWlV@_3m|qSM>Yf>Zr!SahmpgeVbCGbO~>aGFM;R)DXB$dI{Ro zh4+{iz>5dwI|N6%zdp7G8;J-Zmd`v1c3!u!!)rONW|R`uoQF>gLmd3C1CCaM{@His+K3$aoH?_;uYEk2GsT zo3w6JaT8NCXLudD`g$6glOpU);9Db@fJZ=zaa5j+lErz5LN&rZAE?7TAvD&E&Y;}H zm@UVQ6|MF4!vJ4hz*|99u+0Q%X?5YwDwnw(OF>LKH1(EucJXYsKet!gMzNmlnCE}C z>(pW2`!-Vs{j9HF79ABm_w|LnX_cV3M}Ths$a#Yv8GEX%A)9rp{T?tS01qoJ+g!Hd z5Db~L+vq6!Jmy>$;AKtHnzJz`m-_;ws#;pvn#J^68`SUc=I-RJmzLPJ0-y?oMTy~- zQq*$w&@(GWh@?W#Y1BvSRTtMKbjkS;#peS)98p;Q@+gP!wy%+!rXe#L*!nA|LlZd`C~mE8O`rsvgv!O^;% ztI>&mP%8IK4zI%$6Aq351#EG>uxx52_OdnZ6gX7}H*0~7c-X`zbqX-X!_-U!7j*9` zSgsXSk&Zn`7s3j~w8diBR@Wr5UFk3+} zZXgcj@(G=s=hw>gLg1S9iV#`C=IurW^*BY7@AURZgLii~ z4}V)g8{sT=#Z^HCR)!zMnAu6u0>ctm)b;mcIQL=yFQzypNUI|o!1M9KW|@eFp{1M8 zE#n;eE^wZX@vTPTb}}_eFKKgzW}oT`fTbA0jc9E7MLwA{SRXw|8{MoF2W$NNr_V#G ze9&BgJ|n#LqXu_jBAe{6JVZX1P>T~sZ3d6#u4UEF2GpDFQItU0-MlIp3VWHMV!W+Q z*G4vyR&{R)>_P$4F>jVHch@wQwb@Obq#VQSkE`s3OJ~ijXEm-1+cHOBjgnfs8{mH3 zm^yth?kb)BtElPLk1`H{t=PWTly6M6&xsa2yD_H&Um*!#0k3zyK;}g8SX+w#{S<{< zwP^W23*-I%5~5+!k-plE%3X_b+{E7H1|2iFn}C#t=vG55j|dL{>?jSh5ZLeoVs~Cn zskM_aG&5yPWlT|1$nB1pa^u--EccCrg;m@y`cW2mZqSt|((4=@bDzXCDmXb8FUlb^ z&Moo}nB#9dmFrc6zbsWDKJ7C%`)fLa(yPArQ8qpPDFVMGs0(Mi=p z)u+p%^D;7b@FcM-uVkIjtB3VAVW5?$HXVgrQk`uY2zyb!`>4&SaA(i#LWcS$Wf!3L zv49VXVuQFs8=#&>{1|_n(DwODLJ-N7MQhKhwL#kT@r0EJ%W7-ipTUGauvr{&ZhAZ# z!))D`8!;*MZt{>YW_g)3Yc1L%AZ5!uH&^HW^d*YQW%d50JIGy}mB`7lt-erVkriaoA=vc@qP1w?urevNSw-l9NdS>IG?y1H zX%#`-VwQVMd#fUn2-Btv`nsNCe@b<@rPUGgiB&b5{RtIgph^WFA_EuO^^ zOlfzlZr;y|wd8TkPoz{A++y8{wzd?`Hl<)=|4TBn?m5g!wZrAs4FDuy1B@U_$gJ{8 zJ$CCcbkr69sPKT{vZilKfohAPS8k$lp6mw#pwgU;8M(`StJfzsdb4pYdF4J9D@c#2 zG9%yqns#*09=Wk}h}IthNv|V)zv8$ge!&i1lcj(ruGV%I>4fN9r2n%~O22LFdma*O z(MQwM0r8Z?4Z|ru2+}}cPJ?!QOfxrQK*Tu8`BP!@CRH>xF_mo3hJ>ewEdog@7s8+B zZLu#k24q-m-Q9HifG(y>X%FL(rT6?zu2ir}&)O;$!ol%iV<lTi}^L#-rAMm~BZ-7u#Y^r7&Ktr5$G*Y%MxJ;vNBdkz7g!s(Rsr#Re z#7CW5USrNx2J0(wh{3abopYVTXKG@TTO1vUpD?V&=8> z-&#DA+cV=o+hgN-mdd(g7uU*~A|gVCH4i##e>2wZ_;sDtRuvuJIeA&!eo|_LUs%Fk zySSpbdHdV6pu^EJPMT@z3nzQIUt4e-`Ra9Fj8#w!hb_J|4UtcVd#{2gKqiX}4-&X! zesMO3a5@?UNBV@T%!M|lSrKESXUeZNeSC`j1ld!_5(n5jsdVzu+DlHq(}D^@63Cl8}{o*Td3Easbi9C zf)&q7^waDqXYZe8Kk95ZQY&G+$ftc2`);fnsl9EF&%V2p(aakr^m;A&_s?VQnTRA( z<3Ue0ax!{$Vy#&Tt}$kYY0N2?np$iSc|<{t9~tkhJ|;!az8I^E8D1}shd<}TEmocP zvGK=$d;QNSSqt$>L0mL9vRIr|Jk0bt%+%x@3OF(3AoeCW4lF|JR{;OKE!&J zd4qZ6)y3E0r*D@|Y%`+su~a|Xk?bcW*wwq8Z?KOl;p1Qw{V`l{gb^nJ+7@MffD+ZA z2VdFcaRC220Wi%{tug^k)t@OT0HzoXJEINmk+OLsb=LS1pCgORiU{Wib)7S23vp5e zYm4t0hUgZ`+7OjIk-lM{u{*-V=oFliXsB=?J@S;rR-LtP}pqp64?_w)N=1xDK=Z zv$M~{((PKUhPufm&i;36I!1Ji32vUy?#bpl1ipOAn4rBFyHhx}>CQ)g9o=4LLhe#J z0sq9mch#W=^U3y4=;p^ ztnRq&W4NTLYYzQ=+2!ZT4PH&YiXwyZwN;Dc7);aSuI_hXE5BwW=Q5^N3Adt4@e^BR z=95;%!f&SE7GtK9Z!^W;JKLZ;5&P}t2&GqTzL4!bC_|}--nz@(a(tszW(%59%8}qJ z3mg&D)t18$F;8HnnEb|^%T^&V#@wo)ZDDP{ta+0?H}oK&>81~>#oZ@dd#<{1z~3=5 z?>;cuzShUd&NaUns|SIg4NKpFeDn)WRN(nF;ovg1N%RuYAOCi){h@Ig zX+}WLYC$SEM*K#>V8h((JVpvvduEJkGjyH_-tNHsd|w{{N0aEu?J_iFK0gvLAOSkyr6l!Gx2=;f%n%HcH>a=h3rWsd)T$N}lsQ8|#^Y zaSgk`=qKjuE*0HdcQmLfl(qpjqN4pG8pyBK)UY>lFiW%(YF+@ZnKN|* zyy^2jO?7b~gPzc&KI;+Vq7gz-T&zatG3)ZWSsaE(Azo|hzz>{&Z+%|Ud2X4DA2tZ_ z95w()(}evB)u@98;7FR5kcDrCrLX?)r0(wN14hL4mo^Ce*w(K}R|HNUJ^Kq2M53KG zb~@;}fv{NuFF@nH4V2~Z)myigSSnP01N7i|D4SZhj&L9}c2yZEHj}3bqoJIP*KuWZlYS$R9h0){uiN@RcF;F>?hOlb*oYE2o;QXlDrua^tj z8ABb%#*~~O`N6-P#c?bJDP)op#4v!`)u5r2)yQ06BduyMMc@L|>=ZF4Nt^sOn#<&Z zzP3OO%+U56e^$WBvUdyvqq)09M$TaDf@_nX#%y;&59~+0@7u%`S)cqY z&Zgj%ydJ__-gM8Ptz%$I%)M;Ic_ta*WY1R(3y6XNCiH4LANcOQa}%DisFq**)e)~H z0qB~CRJ=}y1K*C_sT-qe5EA*(afj$rH$N}AS{EWLHkpdByCC>EU%(oL^8rL8Md>mZ zq7A9>$p1J|sg`9tlDMOJ97%*|#ig|O7^rV~8w(9$SfBPH>` z#)J{9Si?V!qNmdqYQ#Z|H^$C0?>^_UOfI)@ZFjeDoEYPp^CM1d=Ozi4pFo^_yQR8t zjqUg-FEPQ&Mi(({;$2j!7E{{2G`<-WmG_VAK-uG&8rGSEsn2ipvk8O`FHjF0^ ztUClxq!pjUQW3T-)AUs52kmw*7qFM@N-z&bVElw17!pB0W~=$35AN)I{H_3wpdvw+ zHQA340tKq9*|bA`{DE-u{+Q~Oky*D?hC#WCCO1@?Bub~c2-0!I1|gU1GIuuLBj7uq zWjV2BFxBKl zd-PPvw5~qGujD+_3G<9$!*XYn8_$N6)hi*)3JNqBZRAtTNy~=}(!2haYW?FObz6&et8Ln~T^q4$)9W6~<(D1HZNfB$hhpj@*%S1+jHRwQ<)tpl zMA+(Wm9l{u-`y48T~_ulY5&R4xv~7MbN<$nJ11qGLwUZ@8E=cbokwCLM-3e;DjerV z27WC{b^6$c9rrn0wsSGGv>c`vxiiHuUxb}5*z|GO{ zlCt)~+dvp;&NOpLVCCNUQPxjjv;)=m5}JnS(Krcuy^Nub?QE_jDUxdq8F|; zh3hZ_6!Y74V7o(L->F?2$b@{K6FUCXQY*L)YrY@I`^Jf_sJ=5FnGr+)&c1!9Z6l== zSYR~B;cC$`NX{GaMktQ88~So}199j$05Rf=5g0b9$~y22aG``X_G*0fYP@8quRM3; z8IWVBuU>f16Buu=Z<`G#|1zi#kXiaz%Zs}#ECO4OpTuBd5~VDhIw1>u?bTj2Ki1q- zhm21+wd;2C3y9~*4hFCMakEbSom7OT|L#r`vtzq{cE@UNjpxoM>VtC}*uHr9EHyG_ zWCt$wBR+(W>f5?-OJ$2c-bWeRJBf=@cIAz>R_& z#9?SLM#Kgd@POMrV(fH6l>N|(1Lz|a(bWaHz*Na>3x&cZFM&nj#42F_7KDs~ zhdg4!%&D*E{fA!&TWovqZ+obMXVD`$K~!gHLao5aoU#}YWfXFW2NIx=y9TULM`EKV z)0{;KS$IovQE+D$XFHUCb>aZ0?vPB}HHlHn$m+vk7jW3y#A(bMn_(%%R{&$RQi`t# zZBww^KuKC|2+LSxLNo^C1Br*!oi>hY@HUPTq7vGl(W(bOU;tFs&KVVtroOA|I9JLF6 zpl0<74kpWkod{2>Bw5iX_3aDAgc!wE>k;MkmJXZlU5?}tu`{zeLs^~Q6v@`KaRZnU zXF+zle>ozU5-sF^XkG_y>!IG&_QG)%jT}xU(0V5NB@w{rTtxdw_TE@jjyXkO9hSt{QQWWzLoq=ze2#Iz{ zLYR`I7`8ZPIgpw7n?a5J@yZ8%-BhZoknw+ zUv;_P0p-}1*~#Lu&f7-xGSenuaiB*D?zm!{B(ex)0NeVgX2 zo}Wd}w>SR{nB=EZyLF9cOhLa19|F2lwDBS?>x&fiBe4q?1R2;MEQm53dNO5zz%8lz zCodg&Mk`?@MZ^J&xm(qn15+c@bR$Hu5&PIuvVGap+NO_%!Za3&C$tAI{G#K4l$wTuGhE5h>f_cN(6U*0+&~CM!vix!s``z4b`>KRSS?sTiVGS?u zFqSSW!pbk2$FgHS1?U1V5r{8O@)~rP_bSAeM_!l9JW?FfmXa}E`3=Ey*rv`OY0Y;1 z4dOc8=sMK_Cu7fJ4^AP$0T>ws8%CLf2rJE6?RBU*ziEq@-_-62FBM3DmFWl*a-)nm z;LPX0!Ock@9-?~+(&1>kv5aV6BXTM20GoA`KBKFn_}(fi9)6XGH6pi%ZqiS{RslMS zb-E#X7otyaLSU6c>w+c=^*=SFP4yvK+kztuX245028X*S|D;R&DiwEv&f&00OCC

`IqCJ49`;D+8}l!x5qqMzdh=Bd!uS=;nrAhF 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�z&gGvjTmu64H!BwjP4@L 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

htmSG*l3Pu< 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[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≪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

;DUS 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

B)?U2xD}{1b^cCH>)e=t-?< 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%0DLKC`X>>^W)ss%R9P;C=L;*?=H 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 fKZ=@d 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

vq6t~krS&N(r=rndfyVUkl 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 Date: Wed, 21 Feb 2024 22:22:51 +0530 Subject: [PATCH 20/53] fix: _getAmountOut normalisation --- contracts/TokenConverter/AbstractTokenConverter.sol | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/contracts/TokenConverter/AbstractTokenConverter.sol b/contracts/TokenConverter/AbstractTokenConverter.sol index 14fae87c..99527939 100644 --- a/contracts/TokenConverter/AbstractTokenConverter.sol +++ b/contracts/TokenConverter/AbstractTokenConverter.sol @@ -1091,13 +1091,11 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// conversion rate after considering incentive(conversionWithIncentive) uint256 conversionWithIncentive = MANTISSA_ONE + incentive; + tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; + /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets /// multiplied by conversionWithIncentive which will be >= 1 - amountOutMantissa = - (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) / - (tokenOutUnderlyingPrice * EXP_SCALE); - - tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; + amountOutMantissa = (amountInMantissa * tokenInToOutConversion) / EXP_SCALE; } /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut From 1642ed21a995298345e5a42f04d76912b61bff1e Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 21 Feb 2024 22:23:42 +0530 Subject: [PATCH 21/53] test: release funds for all assets --- tests/fork/SingleTokenConverter.ts | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts index 4aa3fa16..725c9401 100644 --- a/tests/fork/SingleTokenConverter.ts +++ b/tests/fork/SingleTokenConverter.ts @@ -57,6 +57,40 @@ async function getToken(tokenAddress) { return token; } +export const ASSETS = [ + { name: "AAVE", address: "0xfb6115445Bff7b52FeB98650C87f44907E58f802" }, + { name: "ADA", address: "0x3EE2200Efb3400fAbB9AacF31297cBdD1d435D47" }, + { name: "BCH", address: "0x8fF795a6F4D97E7887C79beA79aba5cc76444aDf" }, + { name: "BETH", address: "0x250632378E573c6Be1AC2f97Fcdf00515d0Aa91B" }, + { name: "BTCB", address: "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c" }, + // { name: "BUSD", address: "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56" }, + { name: "CAKE", address: "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82" }, + { name: "DAI", address: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3" }, + { name: "DOGE", address: "0xbA2aE424d960c26247Dd6c32edC70B295c744C43" }, + { name: "DOT", address: "0x7083609fCE4d1d8Dc0C979AAb8c869Ea2C873402" }, + { name: "ETH", address: "0x2170Ed0880ac9A755fd29B2688956BD959F933F8" }, + { name: "FDUSD", address: "0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409" }, + { name: "FIL", address: "0x0D8Ce2A99Bb6e3B7Db580eD848240e4a0F9aE153" }, + { name: "LINK", address: "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD" }, + { name: "LTC", address: "0x4338665CBB7B2485A8855A139b75D5e34AB0DB94" }, + // { name: "LUNA", address: "0x156ab3346823B651294766e23e6Cf87254d68962" }, + { name: "MATIC", address: "0xCC42724C6683B7E57334c4E856f4c9965ED682bD" }, + { name: "SXP", address: "0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A" }, + { name: "TRX", address: "0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3" }, + // { name: "TRXOLD", address: "0x85EAC5Ac2F758618dFa09bDbe0cf174e7d574D5B" }, + { name: "TUSD", address: "0x40af3827F39D0EAcBF4A168f8D4ee67c121D11c9" }, + // { name: "TUSDOLD", address: "0x14016E85a25aeb13065688cAFB43044C2ef86784" }, + { name: "UNI", address: "0xBf5140A22578168FD562DCcF235E5D43A02ce9B1" }, + { name: "USDC", address: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d" }, + { name: "USDT", address: "0x55d398326f99059fF775485246999027B3197955" }, + // { name: "UST", address: "0x3d4350cD54aeF9f9b2C29435e0fa809957B3F30a" }, + // { name: "VAI", address: "0x4BD17003473389A42DAF6a0a729f6Fdb328BbBd7" }, + // { name: "VRT", address: "0x5f84ce30dc3cf7909101c69086c50de191895883" }, + { name: "WBETH", address: "0xa2e3356610840701bdf5611a53974510ae27e2e1" }, + { name: "XRP", address: "0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE" }, + { name: "XVS", address: "0xcF6BB5389c92Bdda8a3747Ddb454cB7a64626C63" }, +]; + forking(35936683, () => { let protocolShareReserve: Contract; let singleTokenConverterBeaconProxy: Contract; @@ -110,6 +144,12 @@ forking(35936683, () => { await protocolShareReserve.releaseFunds(CORE_POOL, [BTCB]); }); + it("Validates successfull execution of releaseFunds", async () => { + for await (const asset of ASSETS) { + await protocolShareReserve.releaseFunds(CORE_POOL, [asset.address]); + } + }); + it("Validates if released funds are released as expected", async () => { const usdt = await getToken(USDT); From c34f78f57c63683f457d27798d86ce11004674da Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 22 Feb 2024 09:53:44 +0530 Subject: [PATCH 22/53] refactor: fork tests --- tests/fork/SingleTokenConverter.ts | 43 ++++-------------------------- tests/utils.ts | 37 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts index 725c9401..3cf08e90 100644 --- a/tests/fork/SingleTokenConverter.ts +++ b/tests/fork/SingleTokenConverter.ts @@ -1,44 +1,11 @@ import chai from "chai"; import { Contract, Signer } from "ethers"; import { parseUnits } from "ethers/lib/utils"; -import hre, { network } from "hardhat"; +import hre from "hardhat"; -const { expect } = chai; - -const initMainnetUser = async (user: string) => { - await impersonateAccount(user); - return ethers.getSigner(user); -}; - -export async function setForkBlock(blockNumber: number) { - await network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - jsonRpcUrl: process.env.BSC_ARCHIVE_NODE, - blockNumber: blockNumber, - }, - }, - ], - }); -} +import { forking, initMainnetUser } from "../utils"; -const forking = (blockNumber: number, fn: () => void) => { - describe(`riskFundConverter #${blockNumber}`, () => { - before(async () => { - await setForkBlock(blockNumber); - }); - fn(); - }); -}; - -async function impersonateAccount(accountAddress) { - await hre.network.provider.request({ - method: "hardhat_impersonateAccount", - params: [accountAddress], - }); -} +const { expect } = chai; const NORMAL_TIMELOCK = "0x939bD8d64c0A9583A7Dcea9933f7b21697ab6396"; const PROTOCOL_SHARE_RESERVE = "0xCa01D5A9A248a830E9D93231e791B1afFed7c446"; @@ -48,7 +15,7 @@ const PROXY_ADMIN = "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4"; const BTCB_PRIME_CONVERTER = "0xE8CeAa79f082768f99266dFd208d665d2Dd18f53"; const CORE_POOL = "0xfd36e2c2a6789db23113685031d7f16329158384"; -//Assets listed in core pool and need to release mfunds for them +//Assets listed in core pool and need to release funds for them const USDT = "0x55d398326f99059fF775485246999027B3197955"; const BTCB = "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c"; @@ -144,7 +111,7 @@ forking(35936683, () => { await protocolShareReserve.releaseFunds(CORE_POOL, [BTCB]); }); - it("Validates successfull execution of releaseFunds", async () => { + it("Validates successful execution of releaseFunds", async () => { for await (const asset of ASSETS) { await protocolShareReserve.releaseFunds(CORE_POOL, [asset.address]); } diff --git a/tests/utils.ts b/tests/utils.ts index 024fdcf7..fad84efb 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -3,3 +3,40 @@ import BigNumber from "bignumber.js"; export const convertToUnit = (amount: string | number, decimals: number) => { return new BigNumber(amount).times(new BigNumber(10).pow(decimals)).toString(); }; + +const initMainnetUser = async (user: string) => { + await impersonateAccount(user); + return ethers.getSigner(user); +}; + +export async function setForkBlock(blockNumber: number) { + await network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: process.env.BSC_ARCHIVE_NODE, + blockNumber: blockNumber, + }, + }, + ], + }); +} + +const forking = (blockNumber: number, fn: () => void) => { + describe(`riskFundConverter #${blockNumber}`, () => { + before(async () => { + await setForkBlock(blockNumber); + }); + fn(); + }); +}; + +async function impersonateAccount(accountAddress) { + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [accountAddress], + }); +} + +export { initMainnetUser, forking, impersonateAccount }; From 1819985d57eae60fb1e5d6af745e81a1a6191032 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 22 Feb 2024 10:16:02 +0530 Subject: [PATCH 23/53] refactor: tokenInToOutConversion calculation in getAmountIn and getAmountOut --- .../TokenConverter/AbstractTokenConverter.sol | 21 +++++++++++++------ tests/fork/SingleTokenConverter.ts | 3 ++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/contracts/TokenConverter/AbstractTokenConverter.sol b/contracts/TokenConverter/AbstractTokenConverter.sol index 99527939..f342b4e3 100644 --- a/contracts/TokenConverter/AbstractTokenConverter.sol +++ b/contracts/TokenConverter/AbstractTokenConverter.sol @@ -1091,11 +1091,13 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// conversion rate after considering incentive(conversionWithIncentive) uint256 conversionWithIncentive = MANTISSA_ONE + incentive; - tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; - /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets /// multiplied by conversionWithIncentive which will be >= 1 - amountOutMantissa = (amountInMantissa * tokenInToOutConversion) / EXP_SCALE; + amountOutMantissa = + (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) / + (tokenOutUnderlyingPrice * EXP_SCALE); + + tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; } /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut @@ -1137,14 +1139,21 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// conversion rate after considering incentive(conversionWithIncentive) uint256 conversionWithIncentive = MANTISSA_ONE + incentive; - tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0) if (isPrivateConversion) { - amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion; + amountInMantissa = + (amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) / + (tokenInUnderlyingPrice * conversionWithIncentive); } else { - amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up + amountInMantissa = + ((amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) + + (tokenInUnderlyingPrice * conversionWithIncentive) - + tokenOutUnderlyingPrice) / + (tokenInUnderlyingPrice * conversionWithIncentive); //round-up } + + tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; } /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts index 3cf08e90..2dc0d397 100644 --- a/tests/fork/SingleTokenConverter.ts +++ b/tests/fork/SingleTokenConverter.ts @@ -112,8 +112,9 @@ forking(35936683, () => { }); it("Validates successful execution of releaseFunds", async () => { - for await (const asset of ASSETS) { + for (const asset of ASSETS) { await protocolShareReserve.releaseFunds(CORE_POOL, [asset.address]); + console.log("Released Funds for ", asset.name); } }); From 498441f21f92d38cb68bb76f3269cb38758e5ce1 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Mon, 26 Feb 2024 11:40:18 +0530 Subject: [PATCH 24/53] fix: round up for _getAmountIn --- contracts/TokenConverter/AbstractTokenConverter.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/TokenConverter/AbstractTokenConverter.sol b/contracts/TokenConverter/AbstractTokenConverter.sol index f342b4e3..f8c204c5 100644 --- a/contracts/TokenConverter/AbstractTokenConverter.sol +++ b/contracts/TokenConverter/AbstractTokenConverter.sol @@ -1148,8 +1148,7 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo } else { amountInMantissa = ((amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) + - (tokenInUnderlyingPrice * conversionWithIncentive) - - tokenOutUnderlyingPrice) / + (tokenInUnderlyingPrice * conversionWithIncentive) -1) / (tokenInUnderlyingPrice * conversionWithIncentive); //round-up } From 8c73c48d9c5c6ee737712a626684e89a27de7407 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Mon, 26 Feb 2024 16:03:15 +0530 Subject: [PATCH 25/53] tests: add fork tests for getUpdatedAmountIn and getUpdatedAmountOut --- .../TokenConverter/AbstractTokenConverter.sol | 3 +- tests/fork/SingleTokenConverter.ts | 65 ++++++++++++++++--- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/contracts/TokenConverter/AbstractTokenConverter.sol b/contracts/TokenConverter/AbstractTokenConverter.sol index f8c204c5..2701eddf 100644 --- a/contracts/TokenConverter/AbstractTokenConverter.sol +++ b/contracts/TokenConverter/AbstractTokenConverter.sol @@ -1148,7 +1148,8 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo } else { amountInMantissa = ((amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) + - (tokenInUnderlyingPrice * conversionWithIncentive) -1) / + (tokenInUnderlyingPrice * conversionWithIncentive) - + 1) / (tokenInUnderlyingPrice * conversionWithIncentive); //round-up } diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts index 2dc0d397..b2bf51ca 100644 --- a/tests/fork/SingleTokenConverter.ts +++ b/tests/fork/SingleTokenConverter.ts @@ -30,7 +30,6 @@ export const ASSETS = [ { name: "BCH", address: "0x8fF795a6F4D97E7887C79beA79aba5cc76444aDf" }, { name: "BETH", address: "0x250632378E573c6Be1AC2f97Fcdf00515d0Aa91B" }, { name: "BTCB", address: "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c" }, - // { name: "BUSD", address: "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56" }, { name: "CAKE", address: "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82" }, { name: "DAI", address: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3" }, { name: "DOGE", address: "0xbA2aE424d960c26247Dd6c32edC70B295c744C43" }, @@ -40,28 +39,22 @@ export const ASSETS = [ { name: "FIL", address: "0x0D8Ce2A99Bb6e3B7Db580eD848240e4a0F9aE153" }, { name: "LINK", address: "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD" }, { name: "LTC", address: "0x4338665CBB7B2485A8855A139b75D5e34AB0DB94" }, - // { name: "LUNA", address: "0x156ab3346823B651294766e23e6Cf87254d68962" }, { name: "MATIC", address: "0xCC42724C6683B7E57334c4E856f4c9965ED682bD" }, { name: "SXP", address: "0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A" }, { name: "TRX", address: "0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3" }, - // { name: "TRXOLD", address: "0x85EAC5Ac2F758618dFa09bDbe0cf174e7d574D5B" }, { name: "TUSD", address: "0x40af3827F39D0EAcBF4A168f8D4ee67c121D11c9" }, - // { name: "TUSDOLD", address: "0x14016E85a25aeb13065688cAFB43044C2ef86784" }, { name: "UNI", address: "0xBf5140A22578168FD562DCcF235E5D43A02ce9B1" }, { name: "USDC", address: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d" }, { name: "USDT", address: "0x55d398326f99059fF775485246999027B3197955" }, - // { name: "UST", address: "0x3d4350cD54aeF9f9b2C29435e0fa809957B3F30a" }, - // { name: "VAI", address: "0x4BD17003473389A42DAF6a0a729f6Fdb328BbBd7" }, - // { name: "VRT", address: "0x5f84ce30dc3cf7909101c69086c50de191895883" }, { name: "WBETH", address: "0xa2e3356610840701bdf5611a53974510ae27e2e1" }, - { name: "XRP", address: "0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE" }, + // { name: "XRP", address: "0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE" }, { name: "XVS", address: "0xcF6BB5389c92Bdda8a3747Ddb454cB7a64626C63" }, ]; -forking(35936683, () => { +forking(36468100, () => { let protocolShareReserve: Contract; let singleTokenConverterBeaconProxy: Contract; - let proxyAdmin = Contract; + let proxyAdmin: Contract; let singleTokenConverterImplementation = Contract; let timeLockSigner: Signer; @@ -82,6 +75,32 @@ forking(35936683, () => { "InsufficientPoolLiquidity", ); }); + + it("getUpdatedAmountIn and getUpdatedAmountOut", async () => { + const riskFundConvertor = await hre.ethers.getContractAt("RiskFundConverter", RISK_FUND_CONVERTER_PROXY); + for (const asset of ASSETS) { + const assetAddress = asset.address; + const assetToken = await getToken(assetAddress); + const value = await assetToken.decimals(); + + const conversionConfig = await riskFundConvertor.conversionConfigurations(USDT, assetAddress); + if (conversionConfig.conversionAccess != 0) { + const amount = parseUnits("1", value); + const [, amountInMantissaForUser] = await riskFundConvertor.callStatic.getUpdatedAmountIn( + amount, + USDT, + assetAddress, + ); + + const [, amountOutMantissaForUser] = await riskFundConvertor.callStatic.getUpdatedAmountOut( + amountInMantissaForUser, + USDT, + assetAddress, + ); + expect(amountOutMantissaForUser).to.greaterThanOrEqual(amount); + } + } + }); }); describe("Success on releaseFund when getAmountIn and getAmountOut are not rounding up the values", () => { @@ -107,6 +126,32 @@ forking(35936683, () => { .upgrade(RISK_FUND_CONVERTER_PROXY, riskFundConverterImplementation.address); }); + it("getUpdatedAmountIn and getUpdatedAmountOut", async () => { + const riskFundConvertor = await hre.ethers.getContractAt("RiskFundConverter", RISK_FUND_CONVERTER_PROXY); + for (const asset of ASSETS) { + const assetAddress = asset.address; + const assetToken = await getToken(assetAddress); + const value = await assetToken.decimals(); + + const conversionConfig = await riskFundConvertor.conversionConfigurations(USDT, assetAddress); + if (conversionConfig.conversionAccess != 0) { + const amount = parseUnits("1", value); + const [, amountInMantissaForUser] = await riskFundConvertor.callStatic.getUpdatedAmountIn( + amount, + USDT, + assetAddress, + ); + + const [, amountOutMantissaForUser] = await riskFundConvertor.callStatic.getUpdatedAmountOut( + amountInMantissaForUser, + USDT, + assetAddress, + ); + expect(amountOutMantissaForUser).to.equal(amount); + } + } + }); + it("Success for core pool through PROTOCOL_SHARE_RESERVE", async () => { await protocolShareReserve.releaseFunds(CORE_POOL, [BTCB]); }); From fb3f08097a58051c1584278001906e61fa271aad Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Mon, 26 Feb 2024 12:03:07 +0000 Subject: [PATCH 26/53] chore(release): 1.5.0-dev.2 [skip ci] ## [1.5.0-dev.2](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.1...v1.5.0-dev.2) (2024-02-26) ### Bug Fixes * compile typechain for distribution ([f029174](https://github.com/VenusProtocol/protocol-reserve/commit/f029174bc59d71fab87d22bc429287e2aaba738b)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b79121ec..d3965728 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.0-dev.2](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.1...v1.5.0-dev.2) (2024-02-26) + + +### Bug Fixes + +* compile typechain for distribution ([f029174](https://github.com/VenusProtocol/protocol-reserve/commit/f029174bc59d71fab87d22bc429287e2aaba738b)) + ## [1.5.0-dev.1](https://github.com/VenusProtocol/protocol-reserve/compare/v1.4.0...v1.5.0-dev.1) (2024-01-26) diff --git a/package.json b/package.json index b4b60932..00c2e5c8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@venusprotocol/protocol-reserve", "description": "Venus Protocol contracts to manage the income generated by the protocol", - "version": "1.5.0-dev.1", + "version": "1.5.0-dev.2", "author": "Venus", "engines": { "node": ">=18.0.0" From 6c74d7b4bd63c69bc931a238e2f46ed4a6e797ef Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Mon, 26 Feb 2024 19:06:33 +0530 Subject: [PATCH 27/53] fix: amountOutMantissa in _getAmountOut() --- contracts/TokenConverter/AbstractTokenConverter.sol | 7 ++----- tests/fork/SingleTokenConverter.ts | 5 +++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/contracts/TokenConverter/AbstractTokenConverter.sol b/contracts/TokenConverter/AbstractTokenConverter.sol index 2701eddf..dc1a9e77 100644 --- a/contracts/TokenConverter/AbstractTokenConverter.sol +++ b/contracts/TokenConverter/AbstractTokenConverter.sol @@ -1091,13 +1091,10 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// conversion rate after considering incentive(conversionWithIncentive) uint256 conversionWithIncentive = MANTISSA_ONE + incentive; + tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets /// multiplied by conversionWithIncentive which will be >= 1 - amountOutMantissa = - (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) / - (tokenOutUnderlyingPrice * EXP_SCALE); - - tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; + amountOutMantissa = (amountInMantissa * tokenInToOutConversion) / (EXP_SCALE); } /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts index b2bf51ca..e1238290 100644 --- a/tests/fork/SingleTokenConverter.ts +++ b/tests/fork/SingleTokenConverter.ts @@ -47,7 +47,7 @@ export const ASSETS = [ { name: "USDC", address: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d" }, { name: "USDT", address: "0x55d398326f99059fF775485246999027B3197955" }, { name: "WBETH", address: "0xa2e3356610840701bdf5611a53974510ae27e2e1" }, - // { name: "XRP", address: "0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE" }, + { name: "XRP", address: "0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE" }, { name: "XVS", address: "0xcF6BB5389c92Bdda8a3747Ddb454cB7a64626C63" }, ]; @@ -147,7 +147,8 @@ forking(36468100, () => { USDT, assetAddress, ); - expect(amountOutMantissaForUser).to.equal(amount); + console.log("amountOutMantissaForUser", amountOutMantissaForUser.toString()); + expect(amountOutMantissaForUser).to.lessThanOrEqual(amount); } } }); From 8599fb1b14ffd5d8be46b3163809fcbcd8fe15f0 Mon Sep 17 00:00:00 2001 From: Jesus Lanchas Date: Mon, 26 Feb 2024 18:22:35 +0100 Subject: [PATCH 28/53] test: use some utility functions and the expected env variables --- tests/fork/RiskFundConverter.ts | 41 +++--------------------------- tests/fork/SingleTokenConverter.ts | 3 ++- tests/utils.ts | 19 +++++--------- 3 files changed, 13 insertions(+), 50 deletions(-) diff --git a/tests/fork/RiskFundConverter.ts b/tests/fork/RiskFundConverter.ts index bc95d28e..2de562e1 100644 --- a/tests/fork/RiskFundConverter.ts +++ b/tests/fork/RiskFundConverter.ts @@ -2,47 +2,13 @@ import { smock } from "@defi-wonderland/smock"; import chai from "chai"; import { BigNumber } from "ethers"; import { parseUnits } from "ethers/lib/utils"; -import hre, { network } from "hardhat"; +import hre from "hardhat"; import { ResilientOracleInterface } from "../../typechain"; +import { forking, initMainnetUser } from "../utils"; const { expect } = chai; -const initMainnetUser = async (user: string) => { - await impersonateAccount(user); - return ethers.getSigner(user); -}; - -export async function setForkBlock(blockNumber: number) { - await network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - jsonRpcUrl: process.env.BSC_ARCHIVE_NODE, - blockNumber: blockNumber, - }, - }, - ], - }); -} - -const forking = (blockNumber: number, fn: () => void) => { - describe(`riskFundConverter #${blockNumber}`, () => { - before(async () => { - await setForkBlock(blockNumber); - }); - fn(); - }); -}; - -async function impersonateAccount(accountAddress) { - await hre.network.provider.request({ - method: "hardhat_impersonateAccount", - params: [accountAddress], - }); -} - async function getToken(tokenAddress) { const token = await hre.ethers.getContractAt("MockToken", tokenAddress); return token; @@ -76,8 +42,9 @@ forking(33039953, () => { let converterTokenData: object; let amountIn: BigNumber; let amountOutExpected: BigNumber; + const FORK_TESTNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bsctestnet"; - if (process.env.FORK_TESTNET === "true") { + if (FORK_TESTNET) { describe("riskFundConverter", () => { beforeEach(async () => { accessController = await hre.ethers.getContractAt("MockACM", ACM); diff --git a/tests/fork/SingleTokenConverter.ts b/tests/fork/SingleTokenConverter.ts index e1238290..3e59d657 100644 --- a/tests/fork/SingleTokenConverter.ts +++ b/tests/fork/SingleTokenConverter.ts @@ -57,8 +57,9 @@ forking(36468100, () => { let proxyAdmin: Contract; let singleTokenConverterImplementation = Contract; let timeLockSigner: Signer; + const FORK_MAINNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bscmainnet"; - if (process.env.FORK_MAINNET === "true") { + if (FORK_MAINNET) { describe("Single token converter", () => { before(async () => { const singleTokenConverterFactory = await hre.ethers.getContractFactory("SingleTokenConverter"); diff --git a/tests/utils.ts b/tests/utils.ts index fad84efb..4f0d03a7 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -1,10 +1,12 @@ +import { impersonateAccount } from "@nomicfoundation/hardhat-network-helpers"; import BigNumber from "bignumber.js"; +import { ethers, network } from "hardhat"; export const convertToUnit = (amount: string | number, decimals: number) => { return new BigNumber(amount).times(new BigNumber(10).pow(decimals)).toString(); }; -const initMainnetUser = async (user: string) => { +export const initMainnetUser = async (user: string) => { await impersonateAccount(user); return ethers.getSigner(user); }; @@ -15,7 +17,7 @@ export async function setForkBlock(blockNumber: number) { params: [ { forking: { - jsonRpcUrl: process.env.BSC_ARCHIVE_NODE, + jsonRpcUrl: process.env[`ARCHIVE_NODE_${process.env.FORKED_NETWORK || "bscmainnet"}`], blockNumber: blockNumber, }, }, @@ -23,8 +25,8 @@ export async function setForkBlock(blockNumber: number) { }); } -const forking = (blockNumber: number, fn: () => void) => { - describe(`riskFundConverter #${blockNumber}`, () => { +export const forking = (blockNumber: number, fn: () => void) => { + describe(`At block #${blockNumber}`, () => { before(async () => { await setForkBlock(blockNumber); }); @@ -32,11 +34,4 @@ const forking = (blockNumber: number, fn: () => void) => { }); }; -async function impersonateAccount(accountAddress) { - await hre.network.provider.request({ - method: "hardhat_impersonateAccount", - params: [accountAddress], - }); -} - -export { initMainnetUser, forking, impersonateAccount }; +export { initMainnetUser, forking }; From c345ad536b84787bee3528b396cb0fdf7ef3e96d Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Mon, 26 Feb 2024 17:02:06 -0300 Subject: [PATCH 29/53] fix: compile before deploy --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 00c2e5c8..b0018de2 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,7 @@ "scripts": { "compile": "hardhat compile", "test": "hardhat test", - "build": "rm -rf dist && tsc --declaration && hardhat compile", - "publish:dist": "yarn build && cd dist && yarn publish --access public", + "build": "rm -rf dist && hardhat compile && tsc --declaration", "lint": "yarn lint:ts && yarn lint:sol && yarn prettier:check", "lint:ts": "eslint --ignore-path ./.eslintignore --ext .js,.ts .", "lint:sol": "solhint \"contracts/**/*.sol\"", From 1b7d4e47ac4357cd337cbb69d9c9854ab1026ac5 Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Tue, 27 Feb 2024 10:09:24 +0000 Subject: [PATCH 30/53] chore(release): 1.5.0-dev.3 [skip ci] ## [1.5.0-dev.3](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.2...v1.5.0-dev.3) (2024-02-27) ### Bug Fixes * compile before deploy ([c345ad5](https://github.com/VenusProtocol/protocol-reserve/commit/c345ad536b84787bee3528b396cb0fdf7ef3e96d)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3965728..06d0a4ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.0-dev.3](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.2...v1.5.0-dev.3) (2024-02-27) + + +### Bug Fixes + +* compile before deploy ([c345ad5](https://github.com/VenusProtocol/protocol-reserve/commit/c345ad536b84787bee3528b396cb0fdf7ef3e96d)) + ## [1.5.0-dev.2](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.1...v1.5.0-dev.2) (2024-02-26) diff --git a/package.json b/package.json index b0018de2..a5e5db89 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@venusprotocol/protocol-reserve", "description": "Venus Protocol contracts to manage the income generated by the protocol", - "version": "1.5.0-dev.2", + "version": "1.5.0-dev.3", "author": "Venus", "engines": { "node": ">=18.0.0" From d2a99eff7141ad1f1fb435ef707108810287fbb0 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 28 Feb 2024 11:36:34 +0530 Subject: [PATCH 31/53] refactor: remove redundant export statements --- tests/utils.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/utils.ts b/tests/utils.ts index 4f0d03a7..220abb0c 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -33,5 +33,3 @@ export const forking = (blockNumber: number, fn: () => void) => { fn(); }); }; - -export { initMainnetUser, forking }; From a5560325bfe89c505aea5ca57d1ed6d1b6799ef1 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 28 Feb 2024 11:37:32 +0530 Subject: [PATCH 32/53] refactor: implement and utilize _divRoundingUp for safer rounding in calculations --- .../TokenConverter/AbstractTokenConverter.sol | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/contracts/TokenConverter/AbstractTokenConverter.sol b/contracts/TokenConverter/AbstractTokenConverter.sol index dc1a9e77..98bff1e2 100644 --- a/contracts/TokenConverter/AbstractTokenConverter.sol +++ b/contracts/TokenConverter/AbstractTokenConverter.sol @@ -575,9 +575,7 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// If contract has less liquidity for tokenAddressOut than amountOutMantissa if (maxTokenOutReserve < amountOutMantissa) { - amountConvertedMantissa = - ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) / - tokenInToOutConversion; //round-up + amountConvertedMantissa = _divRoundingUp(maxTokenOutReserve * EXP_SCALE, tokenInToOutConversion); amountOutMantissa = maxTokenOutReserve; } } @@ -1143,11 +1141,10 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo (amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) / (tokenInUnderlyingPrice * conversionWithIncentive); } else { - amountInMantissa = - ((amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) + - (tokenInUnderlyingPrice * conversionWithIncentive) - - 1) / - (tokenInUnderlyingPrice * conversionWithIncentive); //round-up + amountInMantissa = _divRoundingUp( + amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE, + tokenInUnderlyingPrice * conversionWithIncentive + ); } tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice; @@ -1179,4 +1176,12 @@ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenCo /// @dev Get base asset address of the destination contract /// @return Address of the base asset function _getDestinationBaseAsset() internal view virtual returns (address) {} + + /// @dev Performs division where the result is rounded up + /// @param numerator The numerator of the division operation + /// @param denominator The denominator of the division operation. Must be non-zero + /// @return The result of the division, rounded up + function _divRoundingUp(uint256 numerator, uint256 denominator) internal pure returns (uint256) { + return (numerator + denominator - 1) / denominator; + } } From 65da55607d26bd43689e4fa5467f6fa7d7904ea1 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 28 Feb 2024 13:47:44 +0530 Subject: [PATCH 33/53] feat: update converters deployment files for bsctestnet --- .../RiskFundConverter_Implementation.json | 68 +++++----- .../bsctestnet/SingleTokenConverterImp.json | 64 ++++----- .../91b55240df7761b1edcdbbc6fc102117.json | 123 ++++++++++++++++++ 3 files changed, 189 insertions(+), 66 deletions(-) create mode 100644 deployments/bsctestnet/solcInputs/91b55240df7761b1edcdbbc6fc102117.json diff --git a/deployments/bsctestnet/RiskFundConverter_Implementation.json b/deployments/bsctestnet/RiskFundConverter_Implementation.json index 1772c07d..9031b0e3 100644 --- a/deployments/bsctestnet/RiskFundConverter_Implementation.json +++ b/deployments/bsctestnet/RiskFundConverter_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", + "address": "0x857ebb8CAcb97DE5ab719320c9FB3aa16076bFe3", "abi": [ { "inputs": [ @@ -1622,30 +1622,30 @@ "type": "function" } ], - "transactionHash": "0x51b90ec28ac939185ebdc2d03af1ddf63add4ec352c4473b396456b0fd7825e7", + "transactionHash": "0x15d4561813dd82369a46d31c6e7b2ad5a6139637eefa02972144edd92efb1302", "receipt": { "to": null, "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", - "transactionIndex": 1, - "gasUsed": "4951352", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe7eb97c3ce0803a746d0c0dc4b0c3653edc508b73f765af46e4d58a18e4f2d54", - "transactionHash": "0x51b90ec28ac939185ebdc2d03af1ddf63add4ec352c4473b396456b0fd7825e7", + "contractAddress": "0x857ebb8CAcb97DE5ab719320c9FB3aa16076bFe3", + "transactionIndex": 0, + "gasUsed": "4953922", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000004000000000000000000000000000000020000000000000", + "blockHash": "0xa97f97dd0b84b693b859cae9bb25f7666ee8db0a3c5f3defaa2a1e0cece48e37", + "transactionHash": "0x15d4561813dd82369a46d31c6e7b2ad5a6139637eefa02972144edd92efb1302", "logs": [ { - "transactionIndex": 1, - "blockNumber": 37698154, - "transactionHash": "0x51b90ec28ac939185ebdc2d03af1ddf63add4ec352c4473b396456b0fd7825e7", - "address": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", + "transactionIndex": 0, + "blockNumber": 38131234, + "transactionHash": "0x15d4561813dd82369a46d31c6e7b2ad5a6139637eefa02972144edd92efb1302", + "address": "0x857ebb8CAcb97DE5ab719320c9FB3aa16076bFe3", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", "logIndex": 0, - "blockHash": "0xe7eb97c3ce0803a746d0c0dc4b0c3653edc508b73f765af46e4d58a18e4f2d54" + "blockHash": "0xa97f97dd0b84b693b859cae9bb25f7666ee8db0a3c5f3defaa2a1e0cece48e37" } ], - "blockNumber": 37698154, - "cumulativeGasUsed": "4982593", + "blockNumber": 38131234, + "cumulativeGasUsed": "4953922", "status": 1, "byzantium": true }, @@ -1654,11 +1654,11 @@ "0x2E7222e51c0f6e98610A1543Aa3836E092CDe62c", "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd" ], - "numDeployments": 2, - "solcInputHash": "e9f683aad829bf9574e4eef6b067ab3e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vBNB_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidArguments\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"MarketNotExistInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetsReservesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"name\":\"PoolAssetsDirectTransferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPoolRegistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPoolRegistry\",\"type\":\"address\"}],\"name\":\"PoolRegistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_COMPTROLLER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NATIVE_WRAPPED\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VBNB\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolAssetReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"getPools\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"poolsWithCore\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolsAssetsDirectTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"setPoolsAssetsDirectTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"errors\":{\"ReentrancyGuardError()\":[{\"details\":\"This error is used to safeguard against reentrancy attacks, ensuring that a certain operation cannot be called recursively within the same transaction.\"}]},\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Reserves of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"corePoolComptroller_\":\"Address of the Comptroller pool\",\"nativeWrapped_\":\"Address of the wrapped native currency\",\"vBNB_\":\"Address of the vBNB\"}},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getPoolAssetReserve(address,address)\":{\"custom:error\":\"MarketNotExistInPool When asset does not exist in the pool(comptroller)ReentrancyGuardError thrown to prevent reentrancy during the function execution\",\"details\":\"Get the Amount of the asset in the risk fund for the specific pool\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"},\"returns\":{\"reserves\":\"Asset's reserve in risk fund\"}},\"getPools(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"poolsWithCore\":\"Array of the pools addresses in which token is available\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256,address[],address[][],bool[][])\":{\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"minimum amount to convert\",\"poolRegistry_\":\"Address of the pool registry\",\"priceOracle_\":\"Resilient oracle address\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPoolRegistry(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"custom:event\":\"PoolRegistryUpdated emits on success\",\"details\":\"Pool registry setter\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"custom:access\":\"Restricted by ACM\",\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"stateVariables\":{\"CORE_POOL_COMPTROLLER\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"NATIVE_WRAPPED\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"VBNB\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\",\"details\":\"This address is used to include the BNB market while in getPools method\"},\"poolsAssetsDirectTransfer\":{\"details\":\"Comptroller(pool) -> Asset -> bool(should transfer directly on true)\"},\"poolsAssetsReserves\":{\"details\":\"Comptroller(pool) -> Asset -> amount\"}},\"title\":\"RiskFundConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"MarketNotExistInPool(address,address)\":[{\"notice\":\"thrown when asset does not exist in the pool\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"ReentrancyGuardError()\":[{\"notice\":\"thrown to prevent reentrancy\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Emitted after updating of the assets reserves amount -> reserve increased by amount\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDirectTransferUpdated(address,address,bool)\":{\"notice\":\"Emitted after the poolsAssetsDirectTransfer mapping is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_COMPTROLLER()\":{\"notice\":\"Address of the core pool comptroller\"},\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"NATIVE_WRAPPED()\":{\"notice\":\"Address of the native wrapped currency\"},\"VBNB()\":{\"notice\":\"Address of the vBNB\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\"},\"getPools(address)\":{\"notice\":\"Get the array of all pools addresses\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"poolRegistry()\":{\"notice\":\"Address of pool registry contract\"},\"poolsAssetsDirectTransfer(address,address)\":{\"notice\":\"The mapping contains the assets for each pool which are sent to RiskFund directly\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"notice\":\"Update the poolsAssetsDirectTransfer mapping\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"RiskFundConverter used for token conversions and sends received token to RiskFund\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/RiskFundConverter.sol\":\"RiskFundConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IComptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IComptroller {\\n function isComptroller() external view returns (bool);\\n\\n function markets(address) external view returns (bool);\\n\\n function getAllMarkets() external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x7d85db8d34103352b25f29f591c1e45159222f0d2bbafaa3fcd42f42bf9a523d\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IPoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IPoolRegistry {\\n /// @notice Get VToken in the Pool for an Asset\\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\\n\\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb38a3b61926e55588096e0657b758b178130386143a5658030d659038ec7075c\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IVToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IVToken {\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x0718e50835da441b2dddcf6d52a671c43d386b96dbcc9eb41d68c3647b82c117\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa =\\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\\n tokenInToOutConversion; //round-up\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa =\\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\\n (tokenOutUnderlyingPrice * EXP_SCALE);\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n\\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\\n converterNetwork.isTokenConverter(msg.sender);\\n if (isPrivateConversion) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n if (isPrivateConversion) {\\n amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion;\\n } else {\\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\\n }\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n}\\n\",\"keccak256\":\"0xdecdaf378a5af7744557fc29495d6db49c6900be1b03bcb6faa2b3a23c9a5c59\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/RiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\nimport { IPoolRegistry } from \\\"../Interfaces/IPoolRegistry.sol\\\";\\nimport { IComptroller } from \\\"../Interfaces/IComptroller.sol\\\";\\nimport { IRiskFund, IRiskFundGetters } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IVToken } from \\\"../Interfaces/IVToken.sol\\\";\\n\\n/// @title RiskFundConverter\\n/// @author Venus\\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the core pool comptroller\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable CORE_POOL_COMPTROLLER;\\n\\n ///@notice Address of the vBNB\\n ///@dev This address is used to include the BNB market while in getPools method\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable VBNB;\\n\\n ///@notice Address of the native wrapped currency\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable NATIVE_WRAPPED;\\n\\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\\n mapping(address => uint256) internal assetsReserves;\\n\\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\\n /// @dev Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\\n\\n /// @notice Address of pool registry contract\\n address public poolRegistry;\\n\\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\\n\\n /// @notice Emitted when pool registry address is updated\\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\\n\\n /// @notice Emitted after updating of the assets reserves\\n /// amount -> reserve increased by amount\\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\\n\\n // Error thrown when comptrollers array length is not equal to assets array length\\n error InvalidArguments();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice thrown when asset does not exist in the pool\\n error MarketNotExistInPool(address comptroller, address asset);\\n\\n /// @notice thrown to prevent reentrancy\\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\\n /// cannot be called recursively within the same transaction.\\n error ReentrancyGuardError();\\n\\n /// @param corePoolComptroller_ Address of the Comptroller pool\\n /// @param vBNB_ Address of the vBNB\\n /// @param nativeWrapped_ Address of the wrapped native currency\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address corePoolComptroller_,\\n address vBNB_,\\n address nativeWrapped_\\n ) {\\n ensureNonzeroAddress(corePoolComptroller_);\\n ensureNonzeroAddress(vBNB_);\\n ensureNonzeroAddress(nativeWrapped_);\\n\\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\\n VBNB = vBNB_;\\n NATIVE_WRAPPED = nativeWrapped_;\\n\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param poolRegistry_ Address of the pool registry\\n /// @param minAmountToConvert_ minimum amount to convert\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address poolRegistry_,\\n uint256 minAmountToConvert_,\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) public initializer {\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n ensureNonzeroAddress(poolRegistry_);\\n poolRegistry = poolRegistry_;\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Pool registry setter\\n /// @param poolRegistry_ Address of the pool registry\\n /// @custom:event PoolRegistryUpdated emits on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:access Only Governance\\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\\n ensureNonzeroAddress(poolRegistry_);\\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\\n poolRegistry = poolRegistry_;\\n }\\n\\n /// @notice Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:access Restricted by ACM\\n function setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) external {\\n _checkAccessAllowed(\\\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\\\");\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return reserves Asset's reserve in risk fund\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n reserves = poolsAssetsReserves[comptroller][asset];\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Reserves of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n tokenBalance = assetsReserves[tokenAddress];\\n }\\n\\n /// @notice Get the array of all pools addresses\\n /// @param tokenAddress Address of the token\\n /// @return poolsWithCore Array of the pools addresses in which token is available\\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\\n\\n if (isAssetListedInCore(tokenAddress)) {\\n uint256 poolsLength = poolsWithCore.length;\\n address[] memory extendedPools = new address[](poolsLength + 1);\\n\\n for (uint256 i; i < poolsLength; ) {\\n extendedPools[i] = poolsWithCore[i];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\\n poolsWithCore = extendedPools;\\n }\\n }\\n\\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\\n assetsReserves[tokenOutAddress] -= amountOut;\\n }\\n\\n /// @notice Hook to perform after converting tokens\\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\\n /// @param tokenInAddress Address of the tokenIn\\n /// @param tokenOutAddress Address of the tokenOut\\n /// @param amountIn Amount of tokenIn transferred\\n /// @param amountOut Amount of tokenOut transferred\\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\\n function _postConversionHook(\\n address tokenInAddress,\\n address tokenOutAddress,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal override {\\n address[] memory pools = getPools(tokenOutAddress);\\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\\n ensureNonzeroValue(assetReserve);\\n\\n uint256 poolsLength = pools.length;\\n uint256 distributedOutShare;\\n uint256 poolAmountInShare;\\n uint256 distributedInShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\\n if (currentPoolsAssetsReserves != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\\n distributedInShare += poolAmountInShare;\\n } else {\\n uint256 distributedDiff = amountOut - distributedOutShare;\\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\\n poolAmountInShare = amountIn - distributedInShare;\\n }\\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n\\n address[] memory pools = getPools(tokenAddress);\\n uint256 assetReserve = assetsReserves[tokenAddress];\\n uint256 poolsLength = pools.length;\\n uint256 distributedShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\\n } else {\\n uint256 distributedDiff = amountDiff - distributedShare;\\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n assetsReserves[tokenAddress] -= amountDiff;\\n }\\n }\\n\\n /// @dev Update the poolAssetsReserves upon transferring the tokens\\n /// @param pool Address of the pool\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @param assetReserve Asset's reserve for the pool\\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\\n /// @custom:event AssetsReservesUpdated emits on success\\n function updatePoolAssetsReserve(\\n address pool,\\n address tokenAddress,\\n uint256 amount,\\n uint256 assetReserve\\n ) internal returns (uint256 poolAmountShare) {\\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\\n }\\n\\n /// @dev Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\\n function _setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) internal {\\n uint256 comptrollersLength = comptrollers.length;\\n\\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 i; i < comptrollersLength; ) {\\n address[] memory poolAssets = assets[i];\\n bool[] memory assetsValues = values[i];\\n uint256 poolAssetsLength = poolAssets.length;\\n\\n if (poolAssetsLength != assetsValues.length) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 j; j < poolAssetsLength; ) {\\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\\n unchecked {\\n ++j;\\n }\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// and transferring funds to the protocol share reserve\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return balanceDifference Amount of asset, for _privateConversion\\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n function _updateAssetsState(address comptroller, address asset)\\n internal\\n override\\n returns (uint256 balanceDifference)\\n {\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 currentBalance = token.balanceOf(address(this));\\n uint256 assetReserve = assetsReserves[asset];\\n if (currentBalance > assetReserve) {\\n unchecked {\\n balanceDifference = currentBalance - assetReserve;\\n }\\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\\n token.safeTransfer(destinationAddress, balanceDifference);\\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\\n\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\\n IRiskFund(destinationAddress).updatePoolState(\\n comptroller,\\n asset,\\n newDestinationBalance - previousDestinationBalance\\n );\\n balanceDifference = 0;\\n }\\n }\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal override {\\n if (convertedTokenInBalance > 0) {\\n emit AssetTransferredToDestination(\\n destinationAddress,\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance\\n );\\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\\n }\\n if (convertedTokenOutBalance > 0) {\\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed in core pool or not\\n /// @param tokenAddress Address of the asset\\n /// @return isAssetListed true if the asset is listed\\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\\n\\n uint256 coreMarketsLength = coreMarkets.length;\\n for (uint256 i; i < coreMarketsLength; ) {\\n isAssetListed = (VBNB == coreMarkets[i])\\n ? (tokenAddress == NATIVE_WRAPPED)\\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\\n\\n if (isAssetListed) {\\n break;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed or not\\n /// @param comptroller Address of the comptroller\\n /// @param asset Address of the asset\\n /// @return isListed true if the asset is listed\\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\\n if (comptroller == CORE_POOL_COMPTROLLER) {\\n isListed = isAssetListedInCore(asset);\\n } else {\\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n }\\n\\n /// @dev Get base asset address of the RiskFund\\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\\n }\\n}\\n\",\"keccak256\":\"0xa9fda55440f25049f1946980b801723cf2111584253a1c11ac1bb7d773cbe39e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b5060405162005aba38038062005aba83398101604081905262000034916200018a565b6200003f8362000081565b6200004a8262000081565b620000558162000081565b6001600160a01b0380841660805282811660a052811660c05262000078620000ac565b505050620001d4565b6001600160a01b038116620000a9576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff1615620001195760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016b576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018557600080fd5b919050565b600080600060608486031215620001a057600080fd5b620001ab846200016d565b9250620001bb602085016200016d565b9150620001cb604085016200016d565b90509250925092565b60805160a05160c05161589362000227600039600081816103e20152612d3b0152600081816103bb0152612c780152600081816106c501528181610d7a01528181612bbf015261349801526158936000f3fe608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614de4565b6106f0565b005b61037b610376366004614e01565b610704565b60408051928352602083019190915201610315565b61036661039e366004614de4565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e43565b6107d0565b610343610425366004614ea2565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614de4565b61091a565b610366610467366004614de4565b61092b565b61036661047a366004614f27565b61093c565b61036661048d366004614fc1565b610973565b610366610b4a565b6104ad6104a8366004614de4565b610c30565b60405161031591906150ae565b61037b6104c8366004614e01565b610dcc565b6103666104db3660046150fb565b610eca565b61037b6104ee366004614e01565b610f71565b61037b610501366004614e01565b61107a565b610519610514366004614ea2565b611179565b604051908152602001610315565b610519610535366004614de4565b6001600160a01b0316600090815261012d602052604090205490565b61036661123e565b61036661056736600461513c565b611252565b610366611299565b610366610582366004614de4565b611324565b6033546001600160a01b0316610301565b61037b6105a6366004614e43565b6113ab565b6103666105b9366004614ea2565b6114a1565b61012f54610301906001600160a01b031681565b6106076105e0366004614ea2565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516103159291906151bf565b6097546001600160a01b0316610301565b61037b610634366004614e43565b6114d7565b6103666115cd565b61036661064f3660046151d3565b61167f565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e43565b61171d565b6103666106a8366004615283565b61184c565b6103666106bb366004614de4565b611bf5565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c7e565b61070181611cd8565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615155565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d55565b508092505050935093915050565b6107c7611c7e565b610701816120ac565b6000808285856107de6121a1565b6107e7836121f6565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610857612236565b6108648a8a8a8a8a61228f565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c7e565b6107018161268a565b610933611c7e565b61070181612707565b61095d6040518060600160405280603c8152602001615822603c9139612784565b61096b868686868686612850565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612b21565b610a97896121f6565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad9878787878787612850565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250612784565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153ec565b9050610cc882612bba565b15610dc75780516000610cdc826001615450565b67ffffffffffffffff811115610cf457610cf46152f4565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615468565b6020026020010151828281518110610d5757610d57615468565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615468565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615155565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d86565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ec05781600181610e9c670de0b6b3a764000085615497565b610ea69190615450565b610eb091906154d4565b610eba91906154eb565b93508092505b5050935093915050565b610ed2611c7e565b610eda612236565b610ee3836121f6565b610eec826121f6565b610ef5816130a7565b82610f0081836130e1565b610f146001600160a01b03821684846133eb565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f5991815260200190565b60405180910390a350610f6c600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561104d57600080fd5b505af1158015611061573d6000803e3d6000fd5b50505050611070858585612d86565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110de57600080fd5b505af11580156110f2573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561115657600080fd5b505af115801561116a573d6000803e3d6000fd5b50505050611070858585611d55565b600061118760c95460021490565b156111be576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c88383613494565b611211576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b611246611c7e565b6112506000613584565b565b6112906040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250612784565b610701816135b5565b60655433906001600160a01b0316811461131b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613584565b61132c611c7e565b611335816121f6565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113b96121a1565b6113c2836121f6565b816001600160a01b0316836001600160a01b031614806113f35750806001600160a01b0316836001600160a01b0316145b1561142a576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611432612236565b61143f8a8a8a8a8a61228f565b90955093506114508888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b6114a9612236565b60006114b583836135ff565b905080156114c8576114c883838361395c565b506114d3600160c955565b5050565b6000808285856114e56121a1565b6114ee836121f6565b816001600160a01b0316836001600160a01b0316148061151f5750806001600160a01b0316836001600160a01b0316145b15611556576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61155e612236565b61156b8a8a8a8a8a613df8565b909550935061157c8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b61160b6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250612784565b6116136121a1565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116b9576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156117145761170c878787848181106116da576116da615468565b90506020020160208101906116ef9190614de4565b86868581811061170157611701615468565b90506040020161184c565b6001016116bc565b50505050505050565b60008082858561172b6121a1565b611734836121f6565b816001600160a01b0316836001600160a01b031614806117655750806001600160a01b0316836001600160a01b0316145b1561179c576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117a4612236565b6117b18a8a8a8a8a613e8a565b90955093508884146117ef576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117fb8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b61186d6040518060600160405280603581526020016157ed60359139612784565b611876836121f6565b61187f826121f6565b6706f05b59d3b20000813511156118d3576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b0316148061190c57506118f6613f47565b6001600160a01b0316836001600160a01b031614155b80611954575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561195157611951615155565b14155b1561198b576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261199d6040830160208401615526565b60038111156119ae576119ae615155565b1480156119bb5750803515155b156119f2576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002611a046040830160208401615526565b6003811115611a1557611a15615155565b1480611a4157506001611a2e6040830160208401615526565b6003811115611a3f57611a3f615155565b145b8015611a56575060ff546001600160a01b0316155b15611a8d576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611afd91908a01908a01615526565b604051611b0d9493929190615547565b60405180910390a36000611b276040840160208501615526565b6003811115611b3857611b38615155565b03611b95576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bef565b81358155611ba96040830160208401615526565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611be957611be9615155565b02179055505b50505050565b611bfd611c7e565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c466033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611ce1816121f6565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d92576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611de657611de6615155565b6003811115611df757611df7615155565b9052509050600081602001516003811115611e1457611e14615155565b03611e4b576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190615578565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f609190615578565b835160ff54919250906000906001600160a01b031615801590612003575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120039190615591565b9050801561201057600091505b600061202483670de0b6b3a7640000615450565b9050836120318287615497565b61203b91906154eb565b965081156120675786612056670de0b6b3a76400008d615497565b61206091906154eb565b975061209e565b8660018161207d670de0b6b3a76400008f615497565b6120879190615450565b61209191906154d4565b61209b91906154eb565b97505b505050505050935093915050565b6001600160a01b0381166121285760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611250576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c954036122885760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b60008061229c8585613fd3565b6122a685886140f3565b91506122b3828686610f71565b915050858110156122fa576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b61230584848361423e565b9550959350505050565b600061231a84610c30565b6001600160a01b038516600090815261012d602052604081205491925090612343908490615450565b905061234e816130a7565b815160008080805b8481101561267657600061012e600089848151811061237757612377615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b031681526020019081526020016000205490508060001461266d576123d86001876154d4565b821015612438576124048883815181106123f4576123f4615468565b60200260200101518c8b8a6142b8565b61240e9086615450565b94508661241b828c615497565b61242591906154eb565b93506124318484615450565b9250612533565b6000612444868b6154d4565b90508061012e60008b868151811061245e5761245e615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546124b891906154d4565b925050819055508b6001600160a01b03168984815181106124db576124db615468565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161251d91815260200190565b60405180910390a361252f848c6154d4565b9450505b8b6001600160a01b031688838151811061254f5761254f615468565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af55876040516125b091815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125e1576125e1615468565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561265457600080fd5b505af1158015612668573d6000803e3d6000fd5b505050505b50600101612356565b5050505050505050505050565b600160c955565b612693816121f6565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b612710816121f6565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906127d0903390869060040161560b565b602060405180830381865afa1580156127ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128119190615591565b9050806114d3573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b9392919061562d565b8483811415806128605750808214155b15612897576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b175760008686838181106128b6576128b6615468565b90506020028101906128c89190615659565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945088925087915085905081811061291057612910615468565b90506020028101906129229190615659565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508451835193945092831491506129959050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b08578281815181106129b2576129b2615468565b602002602001015161013060008e8e898181106129d1576129d1615468565b90506020020160208101906129e69190614de4565b6001600160a01b03166001600160a01b031681526020019081526020016000206000868481518110612a1a57612a1a615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a6b57612a6b615468565b60200260200101516001600160a01b03168c8c87818110612a8e57612a8e615468565b9050602002016020810190612aa39190614de4565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612adf57612adf615468565b6020026020010151604051612af8911515815260200190565b60405180910390a3600101612998565b5083600101935050505061289a565b5050505050505050565b600054610100900460ff16612b9e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612ba784614391565b612baf61441f565b611bef8383836144a4565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612c1b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c4391908101906153ec565b805190915060005b81811015612d7e57828181518110612c6557612c65615468565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d3957846001600160a01b0316838281518110612cc157612cc1615468565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d2a91906156c1565b6001600160a01b031614612d6f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d7e57600101612c4b565b505050919050565b60008084600003612dc3576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612e1757612e17615155565b6003811115612e2857612e28615155565b9052509050600081602001516003811115612e4557612e45615155565b03612e7c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ee0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f049190615578565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f919190615578565b835160ff54919250906001600160a01b031615801590613031575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa15801561300d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130319190615591565b1561303a575060005b600061304e82670de0b6b3a7640000615450565b9050613062670de0b6b3a764000084615497565b8161306d868d615497565b6130779190615497565b61308191906154eb565b96508261308e8286615497565b61309891906154eb565b95505050505050935093915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015613141573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131659190615578565b9050808211156131a1576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d60205260408120546131c590836154d4565b905082811015611bef5780830360006131dd86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b828110156133b15761012e600086838151811061321f5761321f615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133a95761327d6001846154d4565b8110156132ba576132a985828151811061329957613299615468565b60200260200101518b88876142b8565b6132b39083615450565b91506133a9565b60006132c683886154d4565b90508061012e60008885815181106132e0576132e0615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461333a91906154d4565b925050819055508a6001600160a01b031686838151811061335d5761335d615468565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161339f91815260200190565b60405180910390a3505b600101613200565b506001600160a01b038916600090815261012d6020526040812080548792906133db9084906154d4565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f6c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614569565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134df576134d882612bba565b905061357e565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa15801561354c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357091906156c1565b6001600160a01b0316141590505b92915050565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561070181614651565b6135be816130a7565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b600061360b8383613494565b613654576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156136b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136da9190615578565b6001600160a01b038516600090815261012d602052604090205490915080821115613953576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff16156139535760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa158015613798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bc9190615578565b60fe549091506137d9906001600160a01b038681169116876133eb565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561383e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138629190615578565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac353789896138cd86866154d4565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561393457600080fd5b505af1158015613948573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613966613f47565b60fe5460ff549192506001600160a01b03908116916000911615613deb5760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156139f5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a1d91908101906156de565b8151919350915060005b81811015613de657828181518110613a4157613a41615468565b602002602001015160000315613de6576000848281518110613a6557613a65615468565b60200260200101516001600160a01b0316636f1a30a8858481518110613a8d57613a8d615468565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613acf939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b119190615799565b91505088811115613b1f5750875b613b29818b6146bb565b613b335750613de6565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bba9190615578565b90508a6001600160a01b031663095ea7b3878581518110613bdd57613bdd615468565b6020026020010151846040518363ffffffff1660e01b8152600401613c179291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c5a9190615591565b50858381518110613c6d57613c6d615468565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613cf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d1b9190615799565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613da49190615578565b9050613db0838c6154d4565b9a50613dbc82826154d4565b613dc69089615450565b97508a600003613dd857505050613de6565b836001019350505050613a27565b505050505b61096b86848388886147f3565b600080613e058585613fd3565b6000613e1287878761107a565b91505087811115613e59576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e6386826140f3565b9250613e70838787610f71565b9250613e7f905085858461423e565b509550959350505050565b600080613e978585613fd3565b6000613ea487878761107a565b915050613eb186826140f3565b9250808314613eec576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613f30576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f3b85858961423e565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613faa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fce91906156c1565b905090565b60ff546000906001600160a01b031615801590614070575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa15801561404c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140709190615591565b9050801580156140bc575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff1660038111156140ba576140ba615155565b145b15610f6c576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa15801561415c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141809190615578565b60fe5490915061419f906001600160a01b038481169133911687614991565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015614204573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142289190615578565b905061423482826154d4565b9695505050505050565b6001600160a01b038316600090815261012d602052604090205481811015614292576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61429c84836149e2565b836142b16001600160a01b03821685856133eb565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142ee908590615497565b6142f891906154eb565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143359084906154d4565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161438191815260200190565b60405180910390a3949350505050565b600054610100900460ff1661440e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614416614a14565b61070181614a99565b600054610100900460ff1661449c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614b16565b600054610100900460ff166145215760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61452a83612707565b61453382611cd8565b61453c816135b5565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b60006145be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b939092919063ffffffff16565b90508051600014806145df5750808060200190518101906145df9190615591565b610f6c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561471c57600080fd5b505af1158015614730573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156147a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147c89190615578565b6147d29190615497565b6147dc91906154eb565b905060fb5481106147ec57600191505b5092915050565b82156148ca5760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b1580156148b157600080fd5b505af11580156148c5573d6000803e3d6000fd5b505050505b80156142b1576001600160a01b038216600090815261012d6020526040812080548392906148f9908490615450565b90915550506001600160a01b03808616600090815261012e6020908152604080832093861683529290529081208054839290614936908490615450565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161498291815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bef9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401613430565b6001600160a01b038216600090815261012d602052604081208054839290614a0b9084906154d4565b90915550505050565b600054610100900460ff16614a915760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614bac565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126835760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614ba28484600085614c32565b90505b9392505050565b600054610100900460ff16614c295760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61125033613584565b606082471015614caa5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614cc691906157bd565b60006040518083038185875af1925050503d8060008114614d03576040519150601f19603f3d011682016040523d82523d6000602084013e614d08565b606091505b5091509150614d1987838387614d26565b925050505b949350505050565b60608315614d95578251600003614d8e576001600160a01b0385163b614d8e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614d1e565b614d1e8383815115614daa5781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157d9565b6001600160a01b038116811461070157600080fd5b8035610dc781614dc4565b600060208284031215614df657600080fd5b8135614ba581614dc4565b600080600060608486031215614e1657600080fd5b833592506020840135614e2881614dc4565b91506040840135614e3881614dc4565b809150509250925092565b600080600080600060a08688031215614e5b57600080fd5b85359450602086013593506040860135614e7481614dc4565b92506060860135614e8481614dc4565b91506080860135614e9481614dc4565b809150509295509295909350565b60008060408385031215614eb557600080fd5b8235614ec081614dc4565b91506020830135614ed081614dc4565b809150509250929050565b60008083601f840112614eed57600080fd5b50813567ffffffffffffffff811115614f0557600080fd5b6020830191508360208260051b8501011115614f2057600080fd5b9250929050565b60008060008060008060608789031215614f4057600080fd5b863567ffffffffffffffff80821115614f5857600080fd5b614f648a838b01614edb565b90985096506020890135915080821115614f7d57600080fd5b614f898a838b01614edb565b90965094506040890135915080821115614fa257600080fd5b50614faf89828a01614edb565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fe357600080fd5b614fec8c614dd9565b9a50614ffa60208d01614dd9565b995061500860408d01614dd9565b985061501660608d01614dd9565b975060808c0135965067ffffffffffffffff8060a08e0135111561503957600080fd5b6150498e60a08f01358f01614edb565b909750955060c08d013581101561505f57600080fd5b61506f8e60c08f01358f01614edb565b909550935060e08d013581101561508557600080fd5b506150968d60e08e01358e01614edb565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150ef5783516001600160a01b0316835292840192918401916001016150ca565b50909695505050505050565b60008060006060848603121561511057600080fd5b833561511b81614dc4565b9250602084013561512b81614dc4565b929592945050506040919091013590565b60006020828403121561514e57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106151bb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614ba56020830184615184565b6000806000806000606086880312156151eb57600080fd5b85356151f681614dc4565b9450602086013567ffffffffffffffff8082111561521357600080fd5b61521f89838a01614edb565b9096509450604088013591508082111561523857600080fd5b818801915088601f83011261524c57600080fd5b81358181111561525b57600080fd5b8960208260061b850101111561527057600080fd5b9699959850939650602001949392505050565b6000806000838503608081121561529957600080fd5b84356152a481614dc4565b935060208501356152b481614dc4565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152e657600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561534c5761534c6152f4565b604052919050565b600067ffffffffffffffff82111561536e5761536e6152f4565b5060051b60200190565b600082601f83011261538957600080fd5b8151602061539e61539983615354565b615323565b82815260059290921b840181019181810190868411156153bd57600080fd5b8286015b848110156153e15780516153d481614dc4565b83529183019183016153c1565b509695505050505050565b6000602082840312156153fe57600080fd5b815167ffffffffffffffff81111561541557600080fd5b614d1e84828501615378565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561546357615463615421565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156154cf576154cf615421565b500290565b6000828210156154e6576154e6615421565b500390565b600082615521577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561553857600080fd5b813560048110614ba557600080fd5b84815260208101849052608081016155626040830185615184565b61556f6060830184615184565b95945050505050565b60006020828403121561558a57600080fd5b5051919050565b6000602082840312156155a357600080fd5b81518015158114614ba557600080fd5b60005b838110156155ce5781810151838201526020016155b6565b83811115611bef5750506000910152565b600081518084526155f78160208601602086016155b3565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614ba260408301846155df565b60006001600160a01b0380861683528085166020840152506060604083015261556f60608301846155df565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261568e57600080fd5b83018035915067ffffffffffffffff8211156156a957600080fd5b6020019150600581901b3603821315614f2057600080fd5b6000602082840312156156d357600080fd5b8151614ba581614dc4565b600080604083850312156156f157600080fd5b825167ffffffffffffffff8082111561570957600080fd5b61571586838701615378565b935060209150818501518181111561572c57600080fd5b85019050601f8101861361573f57600080fd5b805161574d61539982615354565b81815260059190911b8201830190838101908883111561576c57600080fd5b928401925b8284101561578a57835182529284019290840190615771565b80955050505050509250929050565b600080604083850312156157ac57600080fd5b505080516020909101519092909150565b600082516157cf8184602087016155b3565b9190910192915050565b602081526000614ba560208301846155df56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a2646970667358221220e9d437e5c5c1c0182f6a30b0ea44454a90e7075c47dc98b514a6b238801ce2d364736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614de4565b6106f0565b005b61037b610376366004614e01565b610704565b60408051928352602083019190915201610315565b61036661039e366004614de4565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e43565b6107d0565b610343610425366004614ea2565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614de4565b61091a565b610366610467366004614de4565b61092b565b61036661047a366004614f27565b61093c565b61036661048d366004614fc1565b610973565b610366610b4a565b6104ad6104a8366004614de4565b610c30565b60405161031591906150ae565b61037b6104c8366004614e01565b610dcc565b6103666104db3660046150fb565b610eca565b61037b6104ee366004614e01565b610f71565b61037b610501366004614e01565b61107a565b610519610514366004614ea2565b611179565b604051908152602001610315565b610519610535366004614de4565b6001600160a01b0316600090815261012d602052604090205490565b61036661123e565b61036661056736600461513c565b611252565b610366611299565b610366610582366004614de4565b611324565b6033546001600160a01b0316610301565b61037b6105a6366004614e43565b6113ab565b6103666105b9366004614ea2565b6114a1565b61012f54610301906001600160a01b031681565b6106076105e0366004614ea2565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516103159291906151bf565b6097546001600160a01b0316610301565b61037b610634366004614e43565b6114d7565b6103666115cd565b61036661064f3660046151d3565b61167f565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e43565b61171d565b6103666106a8366004615283565b61184c565b6103666106bb366004614de4565b611bf5565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c7e565b61070181611cd8565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615155565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d55565b508092505050935093915050565b6107c7611c7e565b610701816120ac565b6000808285856107de6121a1565b6107e7836121f6565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610857612236565b6108648a8a8a8a8a61228f565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c7e565b6107018161268a565b610933611c7e565b61070181612707565b61095d6040518060600160405280603c8152602001615822603c9139612784565b61096b868686868686612850565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612b21565b610a97896121f6565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad9878787878787612850565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250612784565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153ec565b9050610cc882612bba565b15610dc75780516000610cdc826001615450565b67ffffffffffffffff811115610cf457610cf46152f4565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615468565b6020026020010151828281518110610d5757610d57615468565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615468565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615155565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d86565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ec05781600181610e9c670de0b6b3a764000085615497565b610ea69190615450565b610eb091906154d4565b610eba91906154eb565b93508092505b5050935093915050565b610ed2611c7e565b610eda612236565b610ee3836121f6565b610eec826121f6565b610ef5816130a7565b82610f0081836130e1565b610f146001600160a01b03821684846133eb565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f5991815260200190565b60405180910390a350610f6c600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561104d57600080fd5b505af1158015611061573d6000803e3d6000fd5b50505050611070858585612d86565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110de57600080fd5b505af11580156110f2573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561115657600080fd5b505af115801561116a573d6000803e3d6000fd5b50505050611070858585611d55565b600061118760c95460021490565b156111be576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c88383613494565b611211576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b611246611c7e565b6112506000613584565b565b6112906040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250612784565b610701816135b5565b60655433906001600160a01b0316811461131b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613584565b61132c611c7e565b611335816121f6565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113b96121a1565b6113c2836121f6565b816001600160a01b0316836001600160a01b031614806113f35750806001600160a01b0316836001600160a01b0316145b1561142a576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611432612236565b61143f8a8a8a8a8a61228f565b90955093506114508888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b6114a9612236565b60006114b583836135ff565b905080156114c8576114c883838361395c565b506114d3600160c955565b5050565b6000808285856114e56121a1565b6114ee836121f6565b816001600160a01b0316836001600160a01b0316148061151f5750806001600160a01b0316836001600160a01b0316145b15611556576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61155e612236565b61156b8a8a8a8a8a613df8565b909550935061157c8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b61160b6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250612784565b6116136121a1565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116b9576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156117145761170c878787848181106116da576116da615468565b90506020020160208101906116ef9190614de4565b86868581811061170157611701615468565b90506040020161184c565b6001016116bc565b50505050505050565b60008082858561172b6121a1565b611734836121f6565b816001600160a01b0316836001600160a01b031614806117655750806001600160a01b0316836001600160a01b0316145b1561179c576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117a4612236565b6117b18a8a8a8a8a613e8a565b90955093508884146117ef576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117fb8888878761230f565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b61186d6040518060600160405280603581526020016157ed60359139612784565b611876836121f6565b61187f826121f6565b6706f05b59d3b20000813511156118d3576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b0316148061190c57506118f6613f47565b6001600160a01b0316836001600160a01b031614155b80611954575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561195157611951615155565b14155b1561198b576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261199d6040830160208401615526565b60038111156119ae576119ae615155565b1480156119bb5750803515155b156119f2576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002611a046040830160208401615526565b6003811115611a1557611a15615155565b1480611a4157506001611a2e6040830160208401615526565b6003811115611a3f57611a3f615155565b145b8015611a56575060ff546001600160a01b0316155b15611a8d576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611afd91908a01908a01615526565b604051611b0d9493929190615547565b60405180910390a36000611b276040840160208501615526565b6003811115611b3857611b38615155565b03611b95576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bef565b81358155611ba96040830160208401615526565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611be957611be9615155565b02179055505b50505050565b611bfd611c7e565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c466033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611ce1816121f6565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d92576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611de657611de6615155565b6003811115611df757611df7615155565b9052509050600081602001516003811115611e1457611e14615155565b03611e4b576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190615578565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f609190615578565b835160ff54919250906000906001600160a01b031615801590612003575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120039190615591565b9050801561201057600091505b600061202483670de0b6b3a7640000615450565b9050836120318287615497565b61203b91906154eb565b965081156120675786612056670de0b6b3a76400008d615497565b61206091906154eb565b975061209e565b8660018161207d670de0b6b3a76400008f615497565b6120879190615450565b61209191906154d4565b61209b91906154eb565b97505b505050505050935093915050565b6001600160a01b0381166121285760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611250576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c954036122885760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b60008061229c8585613fd3565b6122a685886140f3565b91506122b3828686610f71565b915050858110156122fa576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b61230584848361423e565b9550959350505050565b600061231a84610c30565b6001600160a01b038516600090815261012d602052604081205491925090612343908490615450565b905061234e816130a7565b815160008080805b8481101561267657600061012e600089848151811061237757612377615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b031681526020019081526020016000205490508060001461266d576123d86001876154d4565b821015612438576124048883815181106123f4576123f4615468565b60200260200101518c8b8a6142b8565b61240e9086615450565b94508661241b828c615497565b61242591906154eb565b93506124318484615450565b9250612533565b6000612444868b6154d4565b90508061012e60008b868151811061245e5761245e615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546124b891906154d4565b925050819055508b6001600160a01b03168984815181106124db576124db615468565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161251d91815260200190565b60405180910390a361252f848c6154d4565b9450505b8b6001600160a01b031688838151811061254f5761254f615468565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af55876040516125b091815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125e1576125e1615468565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561265457600080fd5b505af1158015612668573d6000803e3d6000fd5b505050505b50600101612356565b5050505050505050505050565b600160c955565b612693816121f6565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b612710816121f6565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906127d0903390869060040161560b565b602060405180830381865afa1580156127ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128119190615591565b9050806114d3573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b9392919061562d565b8483811415806128605750808214155b15612897576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b175760008686838181106128b6576128b6615468565b90506020028101906128c89190615659565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945088925087915085905081811061291057612910615468565b90506020028101906129229190615659565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508451835193945092831491506129959050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b08578281815181106129b2576129b2615468565b602002602001015161013060008e8e898181106129d1576129d1615468565b90506020020160208101906129e69190614de4565b6001600160a01b03166001600160a01b031681526020019081526020016000206000868481518110612a1a57612a1a615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a6b57612a6b615468565b60200260200101516001600160a01b03168c8c87818110612a8e57612a8e615468565b9050602002016020810190612aa39190614de4565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612adf57612adf615468565b6020026020010151604051612af8911515815260200190565b60405180910390a3600101612998565b5083600101935050505061289a565b5050505050505050565b600054610100900460ff16612b9e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612ba784614391565b612baf61441f565b611bef8383836144a4565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612c1b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c4391908101906153ec565b805190915060005b81811015612d7e57828181518110612c6557612c65615468565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d3957846001600160a01b0316838281518110612cc157612cc1615468565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d2a91906156c1565b6001600160a01b031614612d6f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d7e57600101612c4b565b505050919050565b60008084600003612dc3576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612e1757612e17615155565b6003811115612e2857612e28615155565b9052509050600081602001516003811115612e4557612e45615155565b03612e7c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ee0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f049190615578565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f919190615578565b835160ff54919250906001600160a01b031615801590613031575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa15801561300d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130319190615591565b1561303a575060005b600061304e82670de0b6b3a7640000615450565b9050613062670de0b6b3a764000084615497565b8161306d868d615497565b6130779190615497565b61308191906154eb565b96508261308e8286615497565b61309891906154eb565b95505050505050935093915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015613141573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131659190615578565b9050808211156131a1576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d60205260408120546131c590836154d4565b905082811015611bef5780830360006131dd86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b828110156133b15761012e600086838151811061321f5761321f615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133a95761327d6001846154d4565b8110156132ba576132a985828151811061329957613299615468565b60200260200101518b88876142b8565b6132b39083615450565b91506133a9565b60006132c683886154d4565b90508061012e60008885815181106132e0576132e0615468565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461333a91906154d4565b925050819055508a6001600160a01b031686838151811061335d5761335d615468565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161339f91815260200190565b60405180910390a3505b600101613200565b506001600160a01b038916600090815261012d6020526040812080548792906133db9084906154d4565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f6c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614569565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134df576134d882612bba565b905061357e565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa15801561354c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357091906156c1565b6001600160a01b0316141590505b92915050565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561070181614651565b6135be816130a7565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b600061360b8383613494565b613654576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156136b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136da9190615578565b6001600160a01b038516600090815261012d602052604090205490915080821115613953576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff16156139535760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa158015613798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bc9190615578565b60fe549091506137d9906001600160a01b038681169116876133eb565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561383e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138629190615578565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac353789896138cd86866154d4565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561393457600080fd5b505af1158015613948573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613966613f47565b60fe5460ff549192506001600160a01b03908116916000911615613deb5760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156139f5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a1d91908101906156de565b8151919350915060005b81811015613de657828181518110613a4157613a41615468565b602002602001015160000315613de6576000848281518110613a6557613a65615468565b60200260200101516001600160a01b0316636f1a30a8858481518110613a8d57613a8d615468565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613acf939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b119190615799565b91505088811115613b1f5750875b613b29818b6146bb565b613b335750613de6565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bba9190615578565b90508a6001600160a01b031663095ea7b3878581518110613bdd57613bdd615468565b6020026020010151846040518363ffffffff1660e01b8152600401613c179291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c5a9190615591565b50858381518110613c6d57613c6d615468565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613cf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d1b9190615799565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613da49190615578565b9050613db0838c6154d4565b9a50613dbc82826154d4565b613dc69089615450565b97508a600003613dd857505050613de6565b836001019350505050613a27565b505050505b61096b86848388886147f3565b600080613e058585613fd3565b6000613e1287878761107a565b91505087811115613e59576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e6386826140f3565b9250613e70838787610f71565b9250613e7f905085858461423e565b509550959350505050565b600080613e978585613fd3565b6000613ea487878761107a565b915050613eb186826140f3565b9250808314613eec576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613f30576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f3b85858961423e565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613faa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fce91906156c1565b905090565b60ff546000906001600160a01b031615801590614070575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa15801561404c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140709190615591565b9050801580156140bc575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff1660038111156140ba576140ba615155565b145b15610f6c576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa15801561415c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141809190615578565b60fe5490915061419f906001600160a01b038481169133911687614991565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015614204573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142289190615578565b905061423482826154d4565b9695505050505050565b6001600160a01b038316600090815261012d602052604090205481811015614292576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61429c84836149e2565b836142b16001600160a01b03821685856133eb565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142ee908590615497565b6142f891906154eb565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143359084906154d4565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161438191815260200190565b60405180910390a3949350505050565b600054610100900460ff1661440e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614416614a14565b61070181614a99565b600054610100900460ff1661449c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614b16565b600054610100900460ff166145215760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61452a83612707565b61453382611cd8565b61453c816135b5565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b60006145be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b939092919063ffffffff16565b90508051600014806145df5750808060200190518101906145df9190615591565b610f6c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561471c57600080fd5b505af1158015614730573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156147a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147c89190615578565b6147d29190615497565b6147dc91906154eb565b905060fb5481106147ec57600191505b5092915050565b82156148ca5760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b1580156148b157600080fd5b505af11580156148c5573d6000803e3d6000fd5b505050505b80156142b1576001600160a01b038216600090815261012d6020526040812080548392906148f9908490615450565b90915550506001600160a01b03808616600090815261012e6020908152604080832093861683529290529081208054839290614936908490615450565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161498291815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bef9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401613430565b6001600160a01b038216600090815261012d602052604081208054839290614a0b9084906154d4565b90915550505050565b600054610100900460ff16614a915760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614bac565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126835760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614ba28484600085614c32565b90505b9392505050565b600054610100900460ff16614c295760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61125033613584565b606082471015614caa5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614cc691906157bd565b60006040518083038185875af1925050503d8060008114614d03576040519150601f19603f3d011682016040523d82523d6000602084013e614d08565b606091505b5091509150614d1987838387614d26565b925050505b949350505050565b60608315614d95578251600003614d8e576001600160a01b0385163b614d8e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614d1e565b614d1e8383815115614daa5781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157d9565b6001600160a01b038116811461070157600080fd5b8035610dc781614dc4565b600060208284031215614df657600080fd5b8135614ba581614dc4565b600080600060608486031215614e1657600080fd5b833592506020840135614e2881614dc4565b91506040840135614e3881614dc4565b809150509250925092565b600080600080600060a08688031215614e5b57600080fd5b85359450602086013593506040860135614e7481614dc4565b92506060860135614e8481614dc4565b91506080860135614e9481614dc4565b809150509295509295909350565b60008060408385031215614eb557600080fd5b8235614ec081614dc4565b91506020830135614ed081614dc4565b809150509250929050565b60008083601f840112614eed57600080fd5b50813567ffffffffffffffff811115614f0557600080fd5b6020830191508360208260051b8501011115614f2057600080fd5b9250929050565b60008060008060008060608789031215614f4057600080fd5b863567ffffffffffffffff80821115614f5857600080fd5b614f648a838b01614edb565b90985096506020890135915080821115614f7d57600080fd5b614f898a838b01614edb565b90965094506040890135915080821115614fa257600080fd5b50614faf89828a01614edb565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fe357600080fd5b614fec8c614dd9565b9a50614ffa60208d01614dd9565b995061500860408d01614dd9565b985061501660608d01614dd9565b975060808c0135965067ffffffffffffffff8060a08e0135111561503957600080fd5b6150498e60a08f01358f01614edb565b909750955060c08d013581101561505f57600080fd5b61506f8e60c08f01358f01614edb565b909550935060e08d013581101561508557600080fd5b506150968d60e08e01358e01614edb565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150ef5783516001600160a01b0316835292840192918401916001016150ca565b50909695505050505050565b60008060006060848603121561511057600080fd5b833561511b81614dc4565b9250602084013561512b81614dc4565b929592945050506040919091013590565b60006020828403121561514e57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106151bb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614ba56020830184615184565b6000806000806000606086880312156151eb57600080fd5b85356151f681614dc4565b9450602086013567ffffffffffffffff8082111561521357600080fd5b61521f89838a01614edb565b9096509450604088013591508082111561523857600080fd5b818801915088601f83011261524c57600080fd5b81358181111561525b57600080fd5b8960208260061b850101111561527057600080fd5b9699959850939650602001949392505050565b6000806000838503608081121561529957600080fd5b84356152a481614dc4565b935060208501356152b481614dc4565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152e657600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561534c5761534c6152f4565b604052919050565b600067ffffffffffffffff82111561536e5761536e6152f4565b5060051b60200190565b600082601f83011261538957600080fd5b8151602061539e61539983615354565b615323565b82815260059290921b840181019181810190868411156153bd57600080fd5b8286015b848110156153e15780516153d481614dc4565b83529183019183016153c1565b509695505050505050565b6000602082840312156153fe57600080fd5b815167ffffffffffffffff81111561541557600080fd5b614d1e84828501615378565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561546357615463615421565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156154cf576154cf615421565b500290565b6000828210156154e6576154e6615421565b500390565b600082615521577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561553857600080fd5b813560048110614ba557600080fd5b84815260208101849052608081016155626040830185615184565b61556f6060830184615184565b95945050505050565b60006020828403121561558a57600080fd5b5051919050565b6000602082840312156155a357600080fd5b81518015158114614ba557600080fd5b60005b838110156155ce5781810151838201526020016155b6565b83811115611bef5750506000910152565b600081518084526155f78160208601602086016155b3565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614ba260408301846155df565b60006001600160a01b0380861683528085166020840152506060604083015261556f60608301846155df565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261568e57600080fd5b83018035915067ffffffffffffffff8211156156a957600080fd5b6020019150600581901b3603821315614f2057600080fd5b6000602082840312156156d357600080fd5b8151614ba581614dc4565b600080604083850312156156f157600080fd5b825167ffffffffffffffff8082111561570957600080fd5b61571586838701615378565b935060209150818501518181111561572c57600080fd5b85019050601f8101861361573f57600080fd5b805161574d61539982615354565b81815260059190911b8201830190838101908883111561576c57600080fd5b928401925b8284101561578a57835182529284019290840190615771565b80955050505050509250929050565b600080604083850312156157ac57600080fd5b505080516020909101519092909150565b600082516157cf8184602087016155b3565b9190910192915050565b602081526000614ba560208301846155df56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a2646970667358221220e9d437e5c5c1c0182f6a30b0ea44454a90e7075c47dc98b514a6b238801ce2d364736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "91b55240df7761b1edcdbbc6fc102117", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vBNB_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidArguments\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"MarketNotExistInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetsReservesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"name\":\"PoolAssetsDirectTransferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPoolRegistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPoolRegistry\",\"type\":\"address\"}],\"name\":\"PoolRegistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_COMPTROLLER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NATIVE_WRAPPED\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VBNB\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolAssetReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"getPools\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"poolsWithCore\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolsAssetsDirectTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"setPoolsAssetsDirectTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"errors\":{\"ReentrancyGuardError()\":[{\"details\":\"This error is used to safeguard against reentrancy attacks, ensuring that a certain operation cannot be called recursively within the same transaction.\"}]},\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Reserves of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"corePoolComptroller_\":\"Address of the Comptroller pool\",\"nativeWrapped_\":\"Address of the wrapped native currency\",\"vBNB_\":\"Address of the vBNB\"}},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getPoolAssetReserve(address,address)\":{\"custom:error\":\"MarketNotExistInPool When asset does not exist in the pool(comptroller)ReentrancyGuardError thrown to prevent reentrancy during the function execution\",\"details\":\"Get the Amount of the asset in the risk fund for the specific pool\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"},\"returns\":{\"reserves\":\"Asset's reserve in risk fund\"}},\"getPools(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"poolsWithCore\":\"Array of the pools addresses in which token is available\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256,address[],address[][],bool[][])\":{\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"minimum amount to convert\",\"poolRegistry_\":\"Address of the pool registry\",\"priceOracle_\":\"Resilient oracle address\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPoolRegistry(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"custom:event\":\"PoolRegistryUpdated emits on success\",\"details\":\"Pool registry setter\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"custom:access\":\"Restricted by ACM\",\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"stateVariables\":{\"CORE_POOL_COMPTROLLER\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"NATIVE_WRAPPED\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"VBNB\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\",\"details\":\"This address is used to include the BNB market while in getPools method\"},\"poolsAssetsDirectTransfer\":{\"details\":\"Comptroller(pool) -> Asset -> bool(should transfer directly on true)\"},\"poolsAssetsReserves\":{\"details\":\"Comptroller(pool) -> Asset -> amount\"}},\"title\":\"RiskFundConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"MarketNotExistInPool(address,address)\":[{\"notice\":\"thrown when asset does not exist in the pool\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"ReentrancyGuardError()\":[{\"notice\":\"thrown to prevent reentrancy\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Emitted after updating of the assets reserves amount -> reserve increased by amount\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDirectTransferUpdated(address,address,bool)\":{\"notice\":\"Emitted after the poolsAssetsDirectTransfer mapping is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_COMPTROLLER()\":{\"notice\":\"Address of the core pool comptroller\"},\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"NATIVE_WRAPPED()\":{\"notice\":\"Address of the native wrapped currency\"},\"VBNB()\":{\"notice\":\"Address of the vBNB\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\"},\"getPools(address)\":{\"notice\":\"Get the array of all pools addresses\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"poolRegistry()\":{\"notice\":\"Address of pool registry contract\"},\"poolsAssetsDirectTransfer(address,address)\":{\"notice\":\"The mapping contains the assets for each pool which are sent to RiskFund directly\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"notice\":\"Update the poolsAssetsDirectTransfer mapping\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"RiskFundConverter used for token conversions and sends received token to RiskFund\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/RiskFundConverter.sol\":\"RiskFundConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IComptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IComptroller {\\n function isComptroller() external view returns (bool);\\n\\n function markets(address) external view returns (bool);\\n\\n function getAllMarkets() external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x7d85db8d34103352b25f29f591c1e45159222f0d2bbafaa3fcd42f42bf9a523d\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IPoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IPoolRegistry {\\n /// @notice Get VToken in the Pool for an Asset\\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\\n\\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb38a3b61926e55588096e0657b758b178130386143a5658030d659038ec7075c\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IVToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IVToken {\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x0718e50835da441b2dddcf6d52a671c43d386b96dbcc9eb41d68c3647b82c117\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa = _divRoundingUp(maxTokenOutReserve * EXP_SCALE, tokenInToOutConversion);\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa = (amountInMantissa * tokenInToOutConversion) / (EXP_SCALE);\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n\\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\\n converterNetwork.isTokenConverter(msg.sender);\\n if (isPrivateConversion) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n if (isPrivateConversion) {\\n amountInMantissa =\\n (amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) /\\n (tokenInUnderlyingPrice * conversionWithIncentive);\\n } else {\\n amountInMantissa = _divRoundingUp(\\n amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE,\\n tokenInUnderlyingPrice * conversionWithIncentive\\n );\\n }\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n\\n /// @dev Performs division where the result is rounded up\\n /// @param numerator The numerator of the division operation\\n /// @param denominator The denominator of the division operation. Must be non-zero\\n /// @return The result of the division, rounded up\\n function _divRoundingUp(uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return (numerator + denominator - 1) / denominator;\\n }\\n}\\n\",\"keccak256\":\"0x3a55b64cf2b9fe6872bffa9eabfbeef0a836227a0e8b588d813ae856771a40e9\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/RiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\nimport { IPoolRegistry } from \\\"../Interfaces/IPoolRegistry.sol\\\";\\nimport { IComptroller } from \\\"../Interfaces/IComptroller.sol\\\";\\nimport { IRiskFund, IRiskFundGetters } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IVToken } from \\\"../Interfaces/IVToken.sol\\\";\\n\\n/// @title RiskFundConverter\\n/// @author Venus\\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the core pool comptroller\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable CORE_POOL_COMPTROLLER;\\n\\n ///@notice Address of the vBNB\\n ///@dev This address is used to include the BNB market while in getPools method\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable VBNB;\\n\\n ///@notice Address of the native wrapped currency\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable NATIVE_WRAPPED;\\n\\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\\n mapping(address => uint256) internal assetsReserves;\\n\\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\\n /// @dev Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\\n\\n /// @notice Address of pool registry contract\\n address public poolRegistry;\\n\\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\\n\\n /// @notice Emitted when pool registry address is updated\\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\\n\\n /// @notice Emitted after updating of the assets reserves\\n /// amount -> reserve increased by amount\\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\\n\\n // Error thrown when comptrollers array length is not equal to assets array length\\n error InvalidArguments();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice thrown when asset does not exist in the pool\\n error MarketNotExistInPool(address comptroller, address asset);\\n\\n /// @notice thrown to prevent reentrancy\\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\\n /// cannot be called recursively within the same transaction.\\n error ReentrancyGuardError();\\n\\n /// @param corePoolComptroller_ Address of the Comptroller pool\\n /// @param vBNB_ Address of the vBNB\\n /// @param nativeWrapped_ Address of the wrapped native currency\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address corePoolComptroller_,\\n address vBNB_,\\n address nativeWrapped_\\n ) {\\n ensureNonzeroAddress(corePoolComptroller_);\\n ensureNonzeroAddress(vBNB_);\\n ensureNonzeroAddress(nativeWrapped_);\\n\\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\\n VBNB = vBNB_;\\n NATIVE_WRAPPED = nativeWrapped_;\\n\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param poolRegistry_ Address of the pool registry\\n /// @param minAmountToConvert_ minimum amount to convert\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address poolRegistry_,\\n uint256 minAmountToConvert_,\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) public initializer {\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n ensureNonzeroAddress(poolRegistry_);\\n poolRegistry = poolRegistry_;\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Pool registry setter\\n /// @param poolRegistry_ Address of the pool registry\\n /// @custom:event PoolRegistryUpdated emits on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:access Only Governance\\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\\n ensureNonzeroAddress(poolRegistry_);\\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\\n poolRegistry = poolRegistry_;\\n }\\n\\n /// @notice Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:access Restricted by ACM\\n function setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) external {\\n _checkAccessAllowed(\\\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\\\");\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return reserves Asset's reserve in risk fund\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n reserves = poolsAssetsReserves[comptroller][asset];\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Reserves of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n tokenBalance = assetsReserves[tokenAddress];\\n }\\n\\n /// @notice Get the array of all pools addresses\\n /// @param tokenAddress Address of the token\\n /// @return poolsWithCore Array of the pools addresses in which token is available\\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\\n\\n if (isAssetListedInCore(tokenAddress)) {\\n uint256 poolsLength = poolsWithCore.length;\\n address[] memory extendedPools = new address[](poolsLength + 1);\\n\\n for (uint256 i; i < poolsLength; ) {\\n extendedPools[i] = poolsWithCore[i];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\\n poolsWithCore = extendedPools;\\n }\\n }\\n\\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\\n assetsReserves[tokenOutAddress] -= amountOut;\\n }\\n\\n /// @notice Hook to perform after converting tokens\\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\\n /// @param tokenInAddress Address of the tokenIn\\n /// @param tokenOutAddress Address of the tokenOut\\n /// @param amountIn Amount of tokenIn transferred\\n /// @param amountOut Amount of tokenOut transferred\\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\\n function _postConversionHook(\\n address tokenInAddress,\\n address tokenOutAddress,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal override {\\n address[] memory pools = getPools(tokenOutAddress);\\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\\n ensureNonzeroValue(assetReserve);\\n\\n uint256 poolsLength = pools.length;\\n uint256 distributedOutShare;\\n uint256 poolAmountInShare;\\n uint256 distributedInShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\\n if (currentPoolsAssetsReserves != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\\n distributedInShare += poolAmountInShare;\\n } else {\\n uint256 distributedDiff = amountOut - distributedOutShare;\\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\\n poolAmountInShare = amountIn - distributedInShare;\\n }\\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n\\n address[] memory pools = getPools(tokenAddress);\\n uint256 assetReserve = assetsReserves[tokenAddress];\\n uint256 poolsLength = pools.length;\\n uint256 distributedShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\\n } else {\\n uint256 distributedDiff = amountDiff - distributedShare;\\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n assetsReserves[tokenAddress] -= amountDiff;\\n }\\n }\\n\\n /// @dev Update the poolAssetsReserves upon transferring the tokens\\n /// @param pool Address of the pool\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @param assetReserve Asset's reserve for the pool\\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\\n /// @custom:event AssetsReservesUpdated emits on success\\n function updatePoolAssetsReserve(\\n address pool,\\n address tokenAddress,\\n uint256 amount,\\n uint256 assetReserve\\n ) internal returns (uint256 poolAmountShare) {\\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\\n }\\n\\n /// @dev Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\\n function _setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) internal {\\n uint256 comptrollersLength = comptrollers.length;\\n\\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 i; i < comptrollersLength; ) {\\n address[] memory poolAssets = assets[i];\\n bool[] memory assetsValues = values[i];\\n uint256 poolAssetsLength = poolAssets.length;\\n\\n if (poolAssetsLength != assetsValues.length) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 j; j < poolAssetsLength; ) {\\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\\n unchecked {\\n ++j;\\n }\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// and transferring funds to the protocol share reserve\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return balanceDifference Amount of asset, for _privateConversion\\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n function _updateAssetsState(address comptroller, address asset)\\n internal\\n override\\n returns (uint256 balanceDifference)\\n {\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 currentBalance = token.balanceOf(address(this));\\n uint256 assetReserve = assetsReserves[asset];\\n if (currentBalance > assetReserve) {\\n unchecked {\\n balanceDifference = currentBalance - assetReserve;\\n }\\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\\n token.safeTransfer(destinationAddress, balanceDifference);\\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\\n\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\\n IRiskFund(destinationAddress).updatePoolState(\\n comptroller,\\n asset,\\n newDestinationBalance - previousDestinationBalance\\n );\\n balanceDifference = 0;\\n }\\n }\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal override {\\n if (convertedTokenInBalance > 0) {\\n emit AssetTransferredToDestination(\\n destinationAddress,\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance\\n );\\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\\n }\\n if (convertedTokenOutBalance > 0) {\\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed in core pool or not\\n /// @param tokenAddress Address of the asset\\n /// @return isAssetListed true if the asset is listed\\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\\n\\n uint256 coreMarketsLength = coreMarkets.length;\\n for (uint256 i; i < coreMarketsLength; ) {\\n isAssetListed = (VBNB == coreMarkets[i])\\n ? (tokenAddress == NATIVE_WRAPPED)\\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\\n\\n if (isAssetListed) {\\n break;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed or not\\n /// @param comptroller Address of the comptroller\\n /// @param asset Address of the asset\\n /// @return isListed true if the asset is listed\\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\\n if (comptroller == CORE_POOL_COMPTROLLER) {\\n isListed = isAssetListedInCore(asset);\\n } else {\\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n }\\n\\n /// @dev Get base asset address of the RiskFund\\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\\n }\\n}\\n\",\"keccak256\":\"0xa9fda55440f25049f1946980b801723cf2111584253a1c11ac1bb7d773cbe39e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162005ac638038062005ac683398101604081905262000034916200018a565b6200003f8362000081565b6200004a8262000081565b620000558162000081565b6001600160a01b0380841660805282811660a052811660c05262000078620000ac565b505050620001d4565b6001600160a01b038116620000a9576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff1615620001195760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016b576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018557600080fd5b919050565b600080600060608486031215620001a057600080fd5b620001ab846200016d565b9250620001bb602085016200016d565b9150620001cb604085016200016d565b90509250925092565b60805160a05160c05161589f62000227600039600081816103e20152612d310152600081816103bb0152612c6e0152600081816106c501528181610d7a01528181612bb501526134a6015261589f6000f3fe608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614df0565b6106f0565b005b61037b610376366004614e0d565b610704565b60408051928352602083019190915201610315565b61036661039e366004614df0565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e4f565b6107d0565b610343610425366004614eae565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614df0565b61091a565b610366610467366004614df0565b61092b565b61036661047a366004614f33565b61093c565b61036661048d366004614fcd565b610973565b610366610b4a565b6104ad6104a8366004614df0565b610c30565b60405161031591906150ba565b61037b6104c8366004614e0d565b610dcc565b6103666104db366004615107565b610eb1565b61037b6104ee366004614e0d565b610f58565b61037b610501366004614e0d565b611061565b610519610514366004614eae565b611160565b604051908152602001610315565b610519610535366004614df0565b6001600160a01b0316600090815261012d602052604090205490565b610366611225565b610366610567366004615148565b611239565b610366611280565b610366610582366004614df0565b61130b565b6033546001600160a01b0316610301565b61037b6105a6366004614e4f565b611392565b6103666105b9366004614eae565b611488565b61012f54610301906001600160a01b031681565b6106076105e0366004614eae565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516103159291906151cb565b6097546001600160a01b0316610301565b61037b610634366004614e4f565b6114be565b6103666115b4565b61036661064f3660046151df565b611666565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e4f565b611704565b6103666106a836600461528f565b611833565b6103666106bb366004614df0565b611bdc565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c65565b61070181611cbf565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615161565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d3c565b508092505050935093915050565b6107c7611c65565b610701816120a2565b6000808285856107de612197565b6107e7836121ec565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61085761222c565b6108648a8a8a8a8a612285565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae88888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c65565b61070181612680565b610933611c65565b610701816126fd565b61095d6040518060600160405280603c815260200161582e603c913961277a565b61096b868686868686612846565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612b17565b610a97896121ec565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad9878787878787612846565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e2829000000000000000000000000000081525061277a565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153f8565b9050610cc882612bb0565b15610dc75780516000610cdc82600161545c565b67ffffffffffffffff811115610cf457610cf4615300565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615474565b6020026020010151828281518110610d5757610d57615474565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615474565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615161565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d7c565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ea757610ea1610e9b670de0b6b3a7640000836154a3565b83613089565b93508092505b5050935093915050565b610eb9611c65565b610ec161222c565b610eca836121ec565b610ed3826121ec565b610edc816130b5565b82610ee781836130ef565b610efb6001600160a01b03821684846133f9565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f4091815260200190565b60405180910390a350610f53600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fbc57600080fd5b505af1158015610fd0573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561103457600080fd5b505af1158015611048573d6000803e3d6000fd5b50505050611057858585612d7c565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110c557600080fd5b505af11580156110d9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561113d57600080fd5b505af1158015611151573d6000803e3d6000fd5b50505050611057858585611d3c565b600061116e60c95460021490565b156111a5576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111af83836134a2565b6111f8576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b61122d611c65565b6112376000613590565b565b6112776040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e7432353629000081525061277a565b610701816135c1565b60655433906001600160a01b031681146113025760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613590565b611313611c65565b61131c816121ec565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113a0612197565b6113a9836121ec565b816001600160a01b0316836001600160a01b031614806113da5750806001600160a01b0316836001600160a01b0316145b15611411576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61141961222c565b6114268a8a8a8a8a612285565b909550935061143788888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b61149061222c565b600061149c838361360b565b905080156114af576114af838383613968565b506114ba600160c955565b5050565b6000808285856114cc612197565b6114d5836121ec565b816001600160a01b0316836001600160a01b031614806115065750806001600160a01b0316836001600160a01b0316145b1561153d576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61154561222c565b6115528a8a8a8a8a613e04565b909550935061156388888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b6115f26040518060400160405280601181526020017f7061757365436f6e76657273696f6e282900000000000000000000000000000081525061277a565b6115fa612197565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116a0576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156116fb576116f3878787848181106116c1576116c1615474565b90506020020160208101906116d69190614df0565b8686858181106116e8576116e8615474565b905060400201611833565b6001016116a3565b50505050505050565b600080828585611712612197565b61171b836121ec565b816001600160a01b0316836001600160a01b0316148061174c5750806001600160a01b0316836001600160a01b0316145b15611783576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61178b61222c565b6117988a8a8a8a8a613e96565b90955093508884146117d6576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117e288888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b6118546040518060600160405280603581526020016157f96035913961277a565b61185d836121ec565b611866826121ec565b6706f05b59d3b20000813511156118ba576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b031614806118f357506118dd613f53565b6001600160a01b0316836001600160a01b031614155b8061193b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561193857611938615161565b14155b15611972576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261198460408301602084016154e0565b600381111561199557611995615161565b1480156119a25750803515155b156119d9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026119eb60408301602084016154e0565b60038111156119fc576119fc615161565b1480611a2857506001611a1560408301602084016154e0565b6003811115611a2657611a26615161565b145b8015611a3d575060ff546001600160a01b0316155b15611a74576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611ae491908a01908a016154e0565b604051611af49493929190615501565b60405180910390a36000611b0e60408401602085016154e0565b6003811115611b1f57611b1f615161565b03611b7c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bd6565b81358155611b9060408301602084016154e0565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611bd057611bd0615161565b02179055505b50505050565b611be4611c65565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c2d6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611cc8816121ec565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d79576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611dcd57611dcd615161565b6003811115611dde57611dde615161565b9052509050600081602001516003811115611dfb57611dfb615161565b03611e32576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611e96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eba9190615532565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f479190615532565b835160ff54919250906000906001600160a01b031615801590611fea575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fea919061554b565b90508015611ff757600091505b600061200b83670de0b6b3a764000061545c565b9050811561204b5761201d81866154a3565b670de0b6b3a7640000612030868e6154a3565b61203a91906154a3565b612044919061556d565b975061207d565b61207a670de0b6b3a7640000612061868e6154a3565b61206b91906154a3565b61207583886154a3565b613089565b97505b8361208882876154a3565b612092919061556d565b9650505050505050935093915050565b6001600160a01b03811661211e5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611237576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c9540361227e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b6000806122928585613fdf565b61229c85886140ff565b91506122a9828686610f58565b915050858110156122f0576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b6122fb84848361424a565b9550959350505050565b600061231084610c30565b6001600160a01b038516600090815261012d60205260408120549192509061233990849061545c565b9050612344816130b5565b815160008080805b8481101561266c57600061012e600089848151811061236d5761236d615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b0316815260200190815260200160002054905080600014612663576123ce6001876155a8565b82101561242e576123fa8883815181106123ea576123ea615474565b60200260200101518c8b8a6142c4565b612404908661545c565b945086612411828c6154a3565b61241b919061556d565b9350612427848461545c565b9250612529565b600061243a868b6155a8565b90508061012e60008b868151811061245457612454615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546124ae91906155a8565b925050819055508b6001600160a01b03168984815181106124d1576124d1615474565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161251391815260200190565b60405180910390a3612525848c6155a8565b9450505b8b6001600160a01b031688838151811061254557612545615474565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af55876040516125a691815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125d7576125d7615474565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561264a57600080fd5b505af115801561265e573d6000803e3d6000fd5b505050505b5060010161234c565b5050505050505050505050565b600160c955565b612689816121ec565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b612706816121ec565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906127c69033908690600401615617565b602060405180830381865afa1580156127e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612807919061554b565b9050806114ba573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b93929190615639565b8483811415806128565750808214155b1561288d576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b0d5760008686838181106128ac576128ac615474565b90506020028101906128be9190615665565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945088925087915085905081811061290657612906615474565b90506020028101906129189190615665565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505084518351939450928314915061298b9050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612afe578281815181106129a8576129a8615474565b602002602001015161013060008e8e898181106129c7576129c7615474565b90506020020160208101906129dc9190614df0565b6001600160a01b03166001600160a01b031681526020019081526020016000206000868481518110612a1057612a10615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a6157612a61615474565b60200260200101516001600160a01b03168c8c87818110612a8457612a84615474565b9050602002016020810190612a999190614df0565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612ad557612ad5615474565b6020026020010151604051612aee911515815260200190565b60405180910390a360010161298e565b50836001019350505050612890565b5050505050505050565b600054610100900460ff16612b945760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612b9d8461439d565b612ba561442b565b611bd68383836144b0565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612c11573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c3991908101906153f8565b805190915060005b81811015612d7457828181518110612c5b57612c5b615474565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d2f57846001600160a01b0316838281518110612cb757612cb7615474565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d2091906156cd565b6001600160a01b031614612d65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d7457600101612c41565b505050919050565b60008084600003612db9576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612e0d57612e0d615161565b6003811115612e1e57612e1e615161565b9052509050600081602001516003811115612e3b57612e3b615161565b03612e72576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ed6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efa9190615532565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f879190615532565b835160ff54919250906001600160a01b031615801590613027575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015613003573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613027919061554b565b15613030575060005b600061304482670de0b6b3a764000061545c565b90508261305182866154a3565b61305b919061556d565b9550670de0b6b3a7640000613070878c6154a3565b61307a919061556d565b96505050505050935093915050565b6000816001613098828661545c565b6130a291906155a8565b6130ac919061556d565b90505b92915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561314f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131739190615532565b9050808211156131af576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d60205260408120546131d390836155a8565b905082811015611bd65780830360006131eb86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b828110156133bf5761012e600086838151811061322d5761322d615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133b75761328b6001846155a8565b8110156132c8576132b78582815181106132a7576132a7615474565b60200260200101518b88876142c4565b6132c1908361545c565b91506133b7565b60006132d483886155a8565b90508061012e60008885815181106132ee576132ee615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461334891906155a8565b925050819055508a6001600160a01b031686838151811061336b5761336b615474565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce38836040516133ad91815260200190565b60405180910390a3505b60010161320e565b506001600160a01b038916600090815261012d6020526040812080548792906133e99084906155a8565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f539084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614575565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134ed576134e682612bb0565b90506130af565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa15801561355a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357e91906156cd565b6001600160a01b031614159392505050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556107018161465d565b6135ca816130b5565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b600061361783836134a2565b613660576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156136c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e69190615532565b6001600160a01b038516600090815261012d60205260409020549091508082111561395f576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff161561395f5760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa1580156137a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c89190615532565b60fe549091506137e5906001600160a01b038681169116876133f9565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561384a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061386e9190615532565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac353789896138d986866155a8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561394057600080fd5b505af1158015613954573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613972613f53565b60fe5460ff549192506001600160a01b03908116916000911615613df75760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af1158015613a01573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a2991908101906156ea565b8151919350915060005b81811015613df257828181518110613a4d57613a4d615474565b602002602001015160000315613df2576000848281518110613a7157613a71615474565b60200260200101516001600160a01b0316636f1a30a8858481518110613a9957613a99615474565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613adb939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613af9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1d91906157a5565b91505088811115613b2b5750875b613b35818b6146c7565b613b3f5750613df2565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613ba2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bc69190615532565b90508a6001600160a01b031663095ea7b3878581518110613be957613be9615474565b6020026020010151846040518363ffffffff1660e01b8152600401613c239291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c66919061554b565b50858381518110613c7957613c79615474565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613d03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2791906157a5565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613db09190615532565b9050613dbc838c6155a8565b9a50613dc882826155a8565b613dd2908961545c565b97508a600003613de457505050613df2565b836001019350505050613a33565b505050505b61096b86848388886147ff565b600080613e118585613fdf565b6000613e1e878787611061565b91505087811115613e65576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e6f86826140ff565b9250613e7c838787610f58565b9250613e8b905085858461424a565b509550959350505050565b600080613ea38585613fdf565b6000613eb0878787611061565b915050613ebd86826140ff565b9250808314613ef8576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613f3c576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f4785858961424a565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fda91906156cd565b905090565b60ff546000906001600160a01b03161580159061407c575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015614058573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061407c919061554b565b9050801580156140c8575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff1660038111156140c6576140c6615161565b145b15610f53576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015614168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418c9190615532565b60fe549091506141ab906001600160a01b03848116913391168761499d565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015614210573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142349190615532565b905061424082826155a8565b9695505050505050565b6001600160a01b038316600090815261012d60205260409020548181101561429e576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142a884836149ee565b836142bd6001600160a01b03821685856133f9565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142fa9085906154a3565b614304919061556d565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143419084906155a8565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161438d91815260200190565b60405180910390a3949350505050565b600054610100900460ff1661441a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614422614a20565b61070181614aa5565b600054610100900460ff166144a85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611237614b22565b600054610100900460ff1661452d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614536836126fd565b61453f82611cbf565b614548816135c1565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b60006145ca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b9f9092919063ffffffff16565b90508051600014806145eb5750808060200190518101906145eb919061554b565b610f535760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561472857600080fd5b505af115801561473c573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156147b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147d49190615532565b6147de91906154a3565b6147e8919061556d565b905060fb5481106147f857600191505b5092915050565b82156148d65760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b1580156148bd57600080fd5b505af11580156148d1573d6000803e3d6000fd5b505050505b80156142bd576001600160a01b038216600090815261012d60205260408120805483929061490590849061545c565b90915550506001600160a01b03808616600090815261012e602090815260408083209386168352929052908120805483929061494290849061545c565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161498e91815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bd69085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161343e565b6001600160a01b038216600090815261012d602052604081208054839290614a179084906155a8565b90915550505050565b600054610100900460ff16614a9d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611237614bb8565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126795760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614bae8484600085614c3e565b90505b9392505050565b600054610100900460ff16614c355760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61123733613590565b606082471015614cb65760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614cd291906157c9565b60006040518083038185875af1925050503d8060008114614d0f576040519150601f19603f3d011682016040523d82523d6000602084013e614d14565b606091505b5091509150614d2587838387614d32565b925050505b949350505050565b60608315614da1578251600003614d9a576001600160a01b0385163b614d9a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614d2a565b614d2a8383815115614db65781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157e5565b6001600160a01b038116811461070157600080fd5b8035610dc781614dd0565b600060208284031215614e0257600080fd5b8135614bb181614dd0565b600080600060608486031215614e2257600080fd5b833592506020840135614e3481614dd0565b91506040840135614e4481614dd0565b809150509250925092565b600080600080600060a08688031215614e6757600080fd5b85359450602086013593506040860135614e8081614dd0565b92506060860135614e9081614dd0565b91506080860135614ea081614dd0565b809150509295509295909350565b60008060408385031215614ec157600080fd5b8235614ecc81614dd0565b91506020830135614edc81614dd0565b809150509250929050565b60008083601f840112614ef957600080fd5b50813567ffffffffffffffff811115614f1157600080fd5b6020830191508360208260051b8501011115614f2c57600080fd5b9250929050565b60008060008060008060608789031215614f4c57600080fd5b863567ffffffffffffffff80821115614f6457600080fd5b614f708a838b01614ee7565b90985096506020890135915080821115614f8957600080fd5b614f958a838b01614ee7565b90965094506040890135915080821115614fae57600080fd5b50614fbb89828a01614ee7565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fef57600080fd5b614ff88c614de5565b9a5061500660208d01614de5565b995061501460408d01614de5565b985061502260608d01614de5565b975060808c0135965067ffffffffffffffff8060a08e0135111561504557600080fd5b6150558e60a08f01358f01614ee7565b909750955060c08d013581101561506b57600080fd5b61507b8e60c08f01358f01614ee7565b909550935060e08d013581101561509157600080fd5b506150a28d60e08e01358e01614ee7565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150fb5783516001600160a01b0316835292840192918401916001016150d6565b50909695505050505050565b60008060006060848603121561511c57600080fd5b833561512781614dd0565b9250602084013561513781614dd0565b929592945050506040919091013590565b60006020828403121561515a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106151c7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614bb16020830184615190565b6000806000806000606086880312156151f757600080fd5b853561520281614dd0565b9450602086013567ffffffffffffffff8082111561521f57600080fd5b61522b89838a01614ee7565b9096509450604088013591508082111561524457600080fd5b818801915088601f83011261525857600080fd5b81358181111561526757600080fd5b8960208260061b850101111561527c57600080fd5b9699959850939650602001949392505050565b600080600083850360808112156152a557600080fd5b84356152b081614dd0565b935060208501356152c081614dd0565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152f257600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561535857615358615300565b604052919050565b600067ffffffffffffffff82111561537a5761537a615300565b5060051b60200190565b600082601f83011261539557600080fd5b815160206153aa6153a583615360565b61532f565b82815260059290921b840181019181810190868411156153c957600080fd5b8286015b848110156153ed5780516153e081614dd0565b83529183019183016153cd565b509695505050505050565b60006020828403121561540a57600080fd5b815167ffffffffffffffff81111561542157600080fd5b614d2a84828501615384565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561546f5761546f61542d565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156154db576154db61542d565b500290565b6000602082840312156154f257600080fd5b813560048110614bb157600080fd5b848152602081018490526080810161551c6040830185615190565b6155296060830184615190565b95945050505050565b60006020828403121561554457600080fd5b5051919050565b60006020828403121561555d57600080fd5b81518015158114614bb157600080fd5b6000826155a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000828210156155ba576155ba61542d565b500390565b60005b838110156155da5781810151838201526020016155c2565b83811115611bd65750506000910152565b600081518084526156038160208601602086016155bf565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614bae60408301846155eb565b60006001600160a01b0380861683528085166020840152506060604083015261552960608301846155eb565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261569a57600080fd5b83018035915067ffffffffffffffff8211156156b557600080fd5b6020019150600581901b3603821315614f2c57600080fd5b6000602082840312156156df57600080fd5b8151614bb181614dd0565b600080604083850312156156fd57600080fd5b825167ffffffffffffffff8082111561571557600080fd5b61572186838701615384565b935060209150818501518181111561573857600080fd5b85019050601f8101861361574b57600080fd5b80516157596153a582615360565b81815260059190911b8201830190838101908883111561577857600080fd5b928401925b828410156157965783518252928401929084019061577d565b80955050505050509250929050565b600080604083850312156157b857600080fd5b505080516020909101519092909150565b600082516157db8184602087016155bf565b9190910192915050565b6020815260006130ac60208301846155eb56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a26469706673582212205f6f2758e0a194168e1ee21858c7de5575e3041602ba60b90cda24613fdac4b864736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614df0565b6106f0565b005b61037b610376366004614e0d565b610704565b60408051928352602083019190915201610315565b61036661039e366004614df0565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e4f565b6107d0565b610343610425366004614eae565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614df0565b61091a565b610366610467366004614df0565b61092b565b61036661047a366004614f33565b61093c565b61036661048d366004614fcd565b610973565b610366610b4a565b6104ad6104a8366004614df0565b610c30565b60405161031591906150ba565b61037b6104c8366004614e0d565b610dcc565b6103666104db366004615107565b610eb1565b61037b6104ee366004614e0d565b610f58565b61037b610501366004614e0d565b611061565b610519610514366004614eae565b611160565b604051908152602001610315565b610519610535366004614df0565b6001600160a01b0316600090815261012d602052604090205490565b610366611225565b610366610567366004615148565b611239565b610366611280565b610366610582366004614df0565b61130b565b6033546001600160a01b0316610301565b61037b6105a6366004614e4f565b611392565b6103666105b9366004614eae565b611488565b61012f54610301906001600160a01b031681565b6106076105e0366004614eae565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516103159291906151cb565b6097546001600160a01b0316610301565b61037b610634366004614e4f565b6114be565b6103666115b4565b61036661064f3660046151df565b611666565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e4f565b611704565b6103666106a836600461528f565b611833565b6103666106bb366004614df0565b611bdc565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c65565b61070181611cbf565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615161565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d3c565b508092505050935093915050565b6107c7611c65565b610701816120a2565b6000808285856107de612197565b6107e7836121ec565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61085761222c565b6108648a8a8a8a8a612285565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae88888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c65565b61070181612680565b610933611c65565b610701816126fd565b61095d6040518060600160405280603c815260200161582e603c913961277a565b61096b868686868686612846565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612b17565b610a97896121ec565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad9878787878787612846565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e2829000000000000000000000000000081525061277a565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153f8565b9050610cc882612bb0565b15610dc75780516000610cdc82600161545c565b67ffffffffffffffff811115610cf457610cf4615300565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615474565b6020026020010151828281518110610d5757610d57615474565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615474565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615161565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d7c565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ea757610ea1610e9b670de0b6b3a7640000836154a3565b83613089565b93508092505b5050935093915050565b610eb9611c65565b610ec161222c565b610eca836121ec565b610ed3826121ec565b610edc816130b5565b82610ee781836130ef565b610efb6001600160a01b03821684846133f9565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f4091815260200190565b60405180910390a350610f53600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fbc57600080fd5b505af1158015610fd0573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561103457600080fd5b505af1158015611048573d6000803e3d6000fd5b50505050611057858585612d7c565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110c557600080fd5b505af11580156110d9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561113d57600080fd5b505af1158015611151573d6000803e3d6000fd5b50505050611057858585611d3c565b600061116e60c95460021490565b156111a5576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111af83836134a2565b6111f8576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b61122d611c65565b6112376000613590565b565b6112776040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e7432353629000081525061277a565b610701816135c1565b60655433906001600160a01b031681146113025760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613590565b611313611c65565b61131c816121ec565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113a0612197565b6113a9836121ec565b816001600160a01b0316836001600160a01b031614806113da5750806001600160a01b0316836001600160a01b0316145b15611411576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61141961222c565b6114268a8a8a8a8a612285565b909550935061143788888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b61149061222c565b600061149c838361360b565b905080156114af576114af838383613968565b506114ba600160c955565b5050565b6000808285856114cc612197565b6114d5836121ec565b816001600160a01b0316836001600160a01b031614806115065750806001600160a01b0316836001600160a01b0316145b1561153d576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61154561222c565b6115528a8a8a8a8a613e04565b909550935061156388888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b6115f26040518060400160405280601181526020017f7061757365436f6e76657273696f6e282900000000000000000000000000000081525061277a565b6115fa612197565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116a0576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156116fb576116f3878787848181106116c1576116c1615474565b90506020020160208101906116d69190614df0565b8686858181106116e8576116e8615474565b905060400201611833565b6001016116a3565b50505050505050565b600080828585611712612197565b61171b836121ec565b816001600160a01b0316836001600160a01b0316148061174c5750806001600160a01b0316836001600160a01b0316145b15611783576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61178b61222c565b6117988a8a8a8a8a613e96565b90955093508884146117d6576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117e288888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b6118546040518060600160405280603581526020016157f96035913961277a565b61185d836121ec565b611866826121ec565b6706f05b59d3b20000813511156118ba576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b031614806118f357506118dd613f53565b6001600160a01b0316836001600160a01b031614155b8061193b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561193857611938615161565b14155b15611972576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261198460408301602084016154e0565b600381111561199557611995615161565b1480156119a25750803515155b156119d9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026119eb60408301602084016154e0565b60038111156119fc576119fc615161565b1480611a2857506001611a1560408301602084016154e0565b6003811115611a2657611a26615161565b145b8015611a3d575060ff546001600160a01b0316155b15611a74576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611ae491908a01908a016154e0565b604051611af49493929190615501565b60405180910390a36000611b0e60408401602085016154e0565b6003811115611b1f57611b1f615161565b03611b7c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bd6565b81358155611b9060408301602084016154e0565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611bd057611bd0615161565b02179055505b50505050565b611be4611c65565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c2d6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611cc8816121ec565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d79576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611dcd57611dcd615161565b6003811115611dde57611dde615161565b9052509050600081602001516003811115611dfb57611dfb615161565b03611e32576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611e96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eba9190615532565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f479190615532565b835160ff54919250906000906001600160a01b031615801590611fea575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fea919061554b565b90508015611ff757600091505b600061200b83670de0b6b3a764000061545c565b9050811561204b5761201d81866154a3565b670de0b6b3a7640000612030868e6154a3565b61203a91906154a3565b612044919061556d565b975061207d565b61207a670de0b6b3a7640000612061868e6154a3565b61206b91906154a3565b61207583886154a3565b613089565b97505b8361208882876154a3565b612092919061556d565b9650505050505050935093915050565b6001600160a01b03811661211e5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611237576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c9540361227e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b6000806122928585613fdf565b61229c85886140ff565b91506122a9828686610f58565b915050858110156122f0576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b6122fb84848361424a565b9550959350505050565b600061231084610c30565b6001600160a01b038516600090815261012d60205260408120549192509061233990849061545c565b9050612344816130b5565b815160008080805b8481101561266c57600061012e600089848151811061236d5761236d615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b0316815260200190815260200160002054905080600014612663576123ce6001876155a8565b82101561242e576123fa8883815181106123ea576123ea615474565b60200260200101518c8b8a6142c4565b612404908661545c565b945086612411828c6154a3565b61241b919061556d565b9350612427848461545c565b9250612529565b600061243a868b6155a8565b90508061012e60008b868151811061245457612454615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546124ae91906155a8565b925050819055508b6001600160a01b03168984815181106124d1576124d1615474565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161251391815260200190565b60405180910390a3612525848c6155a8565b9450505b8b6001600160a01b031688838151811061254557612545615474565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af55876040516125a691815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125d7576125d7615474565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561264a57600080fd5b505af115801561265e573d6000803e3d6000fd5b505050505b5060010161234c565b5050505050505050505050565b600160c955565b612689816121ec565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b612706816121ec565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906127c69033908690600401615617565b602060405180830381865afa1580156127e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612807919061554b565b9050806114ba573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b93929190615639565b8483811415806128565750808214155b1561288d576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b0d5760008686838181106128ac576128ac615474565b90506020028101906128be9190615665565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945088925087915085905081811061290657612906615474565b90506020028101906129189190615665565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505084518351939450928314915061298b9050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612afe578281815181106129a8576129a8615474565b602002602001015161013060008e8e898181106129c7576129c7615474565b90506020020160208101906129dc9190614df0565b6001600160a01b03166001600160a01b031681526020019081526020016000206000868481518110612a1057612a10615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a6157612a61615474565b60200260200101516001600160a01b03168c8c87818110612a8457612a84615474565b9050602002016020810190612a999190614df0565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612ad557612ad5615474565b6020026020010151604051612aee911515815260200190565b60405180910390a360010161298e565b50836001019350505050612890565b5050505050505050565b600054610100900460ff16612b945760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612b9d8461439d565b612ba561442b565b611bd68383836144b0565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612c11573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c3991908101906153f8565b805190915060005b81811015612d7457828181518110612c5b57612c5b615474565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d2f57846001600160a01b0316838281518110612cb757612cb7615474565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d2091906156cd565b6001600160a01b031614612d65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d7457600101612c41565b505050919050565b60008084600003612db9576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612e0d57612e0d615161565b6003811115612e1e57612e1e615161565b9052509050600081602001516003811115612e3b57612e3b615161565b03612e72576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ed6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efa9190615532565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f879190615532565b835160ff54919250906001600160a01b031615801590613027575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015613003573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613027919061554b565b15613030575060005b600061304482670de0b6b3a764000061545c565b90508261305182866154a3565b61305b919061556d565b9550670de0b6b3a7640000613070878c6154a3565b61307a919061556d565b96505050505050935093915050565b6000816001613098828661545c565b6130a291906155a8565b6130ac919061556d565b90505b92915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561314f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131739190615532565b9050808211156131af576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d60205260408120546131d390836155a8565b905082811015611bd65780830360006131eb86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b828110156133bf5761012e600086838151811061322d5761322d615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133b75761328b6001846155a8565b8110156132c8576132b78582815181106132a7576132a7615474565b60200260200101518b88876142c4565b6132c1908361545c565b91506133b7565b60006132d483886155a8565b90508061012e60008885815181106132ee576132ee615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461334891906155a8565b925050819055508a6001600160a01b031686838151811061336b5761336b615474565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce38836040516133ad91815260200190565b60405180910390a3505b60010161320e565b506001600160a01b038916600090815261012d6020526040812080548792906133e99084906155a8565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f539084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614575565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134ed576134e682612bb0565b90506130af565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa15801561355a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357e91906156cd565b6001600160a01b031614159392505050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556107018161465d565b6135ca816130b5565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b600061361783836134a2565b613660576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156136c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e69190615532565b6001600160a01b038516600090815261012d60205260409020549091508082111561395f576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff161561395f5760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa1580156137a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c89190615532565b60fe549091506137e5906001600160a01b038681169116876133f9565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561384a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061386e9190615532565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac353789896138d986866155a8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561394057600080fd5b505af1158015613954573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613972613f53565b60fe5460ff549192506001600160a01b03908116916000911615613df75760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af1158015613a01573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a2991908101906156ea565b8151919350915060005b81811015613df257828181518110613a4d57613a4d615474565b602002602001015160000315613df2576000848281518110613a7157613a71615474565b60200260200101516001600160a01b0316636f1a30a8858481518110613a9957613a99615474565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613adb939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613af9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1d91906157a5565b91505088811115613b2b5750875b613b35818b6146c7565b613b3f5750613df2565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613ba2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bc69190615532565b90508a6001600160a01b031663095ea7b3878581518110613be957613be9615474565b6020026020010151846040518363ffffffff1660e01b8152600401613c239291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c66919061554b565b50858381518110613c7957613c79615474565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613d03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2791906157a5565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613db09190615532565b9050613dbc838c6155a8565b9a50613dc882826155a8565b613dd2908961545c565b97508a600003613de457505050613df2565b836001019350505050613a33565b505050505b61096b86848388886147ff565b600080613e118585613fdf565b6000613e1e878787611061565b91505087811115613e65576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e6f86826140ff565b9250613e7c838787610f58565b9250613e8b905085858461424a565b509550959350505050565b600080613ea38585613fdf565b6000613eb0878787611061565b915050613ebd86826140ff565b9250808314613ef8576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613f3c576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f4785858961424a565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fda91906156cd565b905090565b60ff546000906001600160a01b03161580159061407c575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015614058573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061407c919061554b565b9050801580156140c8575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff1660038111156140c6576140c6615161565b145b15610f53576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015614168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418c9190615532565b60fe549091506141ab906001600160a01b03848116913391168761499d565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015614210573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142349190615532565b905061424082826155a8565b9695505050505050565b6001600160a01b038316600090815261012d60205260409020548181101561429e576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142a884836149ee565b836142bd6001600160a01b03821685856133f9565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142fa9085906154a3565b614304919061556d565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143419084906155a8565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161438d91815260200190565b60405180910390a3949350505050565b600054610100900460ff1661441a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614422614a20565b61070181614aa5565b600054610100900460ff166144a85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611237614b22565b600054610100900460ff1661452d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614536836126fd565b61453f82611cbf565b614548816135c1565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b60006145ca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b9f9092919063ffffffff16565b90508051600014806145eb5750808060200190518101906145eb919061554b565b610f535760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561472857600080fd5b505af115801561473c573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156147b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147d49190615532565b6147de91906154a3565b6147e8919061556d565b905060fb5481106147f857600191505b5092915050565b82156148d65760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b1580156148bd57600080fd5b505af11580156148d1573d6000803e3d6000fd5b505050505b80156142bd576001600160a01b038216600090815261012d60205260408120805483929061490590849061545c565b90915550506001600160a01b03808616600090815261012e602090815260408083209386168352929052908120805483929061494290849061545c565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161498e91815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bd69085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161343e565b6001600160a01b038216600090815261012d602052604081208054839290614a179084906155a8565b90915550505050565b600054610100900460ff16614a9d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611237614bb8565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126795760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614bae8484600085614c3e565b90505b9392505050565b600054610100900460ff16614c355760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61123733613590565b606082471015614cb65760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614cd291906157c9565b60006040518083038185875af1925050503d8060008114614d0f576040519150601f19603f3d011682016040523d82523d6000602084013e614d14565b606091505b5091509150614d2587838387614d32565b925050505b949350505050565b60608315614da1578251600003614d9a576001600160a01b0385163b614d9a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614d2a565b614d2a8383815115614db65781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157e5565b6001600160a01b038116811461070157600080fd5b8035610dc781614dd0565b600060208284031215614e0257600080fd5b8135614bb181614dd0565b600080600060608486031215614e2257600080fd5b833592506020840135614e3481614dd0565b91506040840135614e4481614dd0565b809150509250925092565b600080600080600060a08688031215614e6757600080fd5b85359450602086013593506040860135614e8081614dd0565b92506060860135614e9081614dd0565b91506080860135614ea081614dd0565b809150509295509295909350565b60008060408385031215614ec157600080fd5b8235614ecc81614dd0565b91506020830135614edc81614dd0565b809150509250929050565b60008083601f840112614ef957600080fd5b50813567ffffffffffffffff811115614f1157600080fd5b6020830191508360208260051b8501011115614f2c57600080fd5b9250929050565b60008060008060008060608789031215614f4c57600080fd5b863567ffffffffffffffff80821115614f6457600080fd5b614f708a838b01614ee7565b90985096506020890135915080821115614f8957600080fd5b614f958a838b01614ee7565b90965094506040890135915080821115614fae57600080fd5b50614fbb89828a01614ee7565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fef57600080fd5b614ff88c614de5565b9a5061500660208d01614de5565b995061501460408d01614de5565b985061502260608d01614de5565b975060808c0135965067ffffffffffffffff8060a08e0135111561504557600080fd5b6150558e60a08f01358f01614ee7565b909750955060c08d013581101561506b57600080fd5b61507b8e60c08f01358f01614ee7565b909550935060e08d013581101561509157600080fd5b506150a28d60e08e01358e01614ee7565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150fb5783516001600160a01b0316835292840192918401916001016150d6565b50909695505050505050565b60008060006060848603121561511c57600080fd5b833561512781614dd0565b9250602084013561513781614dd0565b929592945050506040919091013590565b60006020828403121561515a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106151c7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614bb16020830184615190565b6000806000806000606086880312156151f757600080fd5b853561520281614dd0565b9450602086013567ffffffffffffffff8082111561521f57600080fd5b61522b89838a01614ee7565b9096509450604088013591508082111561524457600080fd5b818801915088601f83011261525857600080fd5b81358181111561526757600080fd5b8960208260061b850101111561527c57600080fd5b9699959850939650602001949392505050565b600080600083850360808112156152a557600080fd5b84356152b081614dd0565b935060208501356152c081614dd0565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152f257600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561535857615358615300565b604052919050565b600067ffffffffffffffff82111561537a5761537a615300565b5060051b60200190565b600082601f83011261539557600080fd5b815160206153aa6153a583615360565b61532f565b82815260059290921b840181019181810190868411156153c957600080fd5b8286015b848110156153ed5780516153e081614dd0565b83529183019183016153cd565b509695505050505050565b60006020828403121561540a57600080fd5b815167ffffffffffffffff81111561542157600080fd5b614d2a84828501615384565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561546f5761546f61542d565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156154db576154db61542d565b500290565b6000602082840312156154f257600080fd5b813560048110614bb157600080fd5b848152602081018490526080810161551c6040830185615190565b6155296060830184615190565b95945050505050565b60006020828403121561554457600080fd5b5051919050565b60006020828403121561555d57600080fd5b81518015158114614bb157600080fd5b6000826155a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000828210156155ba576155ba61542d565b500390565b60005b838110156155da5781810151838201526020016155c2565b83811115611bd65750506000910152565b600081518084526156038160208601602086016155bf565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614bae60408301846155eb565b60006001600160a01b0380861683528085166020840152506060604083015261552960608301846155eb565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261569a57600080fd5b83018035915067ffffffffffffffff8211156156b557600080fd5b6020019150600581901b3603821315614f2c57600080fd5b6000602082840312156156df57600080fd5b8151614bb181614dd0565b600080604083850312156156fd57600080fd5b825167ffffffffffffffff8082111561571557600080fd5b61572186838701615384565b935060209150818501518181111561573857600080fd5b85019050601f8101861361574b57600080fd5b80516157596153a582615360565b81815260059190911b8201830190838101908883111561577857600080fd5b928401925b828410156157965783518252928401929084019061577d565b80955050505050509250929050565b600080604083850312156157b857600080fd5b505080516020909101519092909150565b600082516157db8184602087016155bf565b9190910192915050565b6020815260006130ac60208301846155eb56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a26469706673582212205f6f2758e0a194168e1ee21858c7de5575e3041602ba60b90cda24613fdac4b864736f6c634300080d0033", "devdoc": { "author": "Venus", "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", @@ -2367,7 +2367,7 @@ "label": "conversionConfigurations", "offset": 0, "slot": "253", - "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5478_storage))" + "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5493_storage))" }, { "astId": 3371, @@ -2402,7 +2402,7 @@ "type": "t_array(t_uint256)45_storage" }, { - "astId": 5704, + "astId": 5719, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "assetsReserves", "offset": 0, @@ -2410,7 +2410,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5711, + "astId": 5726, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "poolsAssetsReserves", "offset": 0, @@ -2418,7 +2418,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 5714, + "astId": 5729, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "poolRegistry", "offset": 0, @@ -2426,7 +2426,7 @@ "type": "t_address" }, { - "astId": 5721, + "astId": 5736, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "poolsAssetsDirectTransfer", "offset": 0, @@ -2478,7 +2478,7 @@ "label": "contract ResilientOracle", "numberOfBytes": "20" }, - "t_enum(ConversionAccessibility)5470": { + "t_enum(ConversionAccessibility)5485": { "encoding": "inplace", "label": "enum IAbstractTokenConverter.ConversionAccessibility", "numberOfBytes": "1" @@ -2497,12 +2497,12 @@ "numberOfBytes": "32", "value": "t_mapping(t_address,t_bool)" }, - "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5478_storage))": { + "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5493_storage))": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => mapping(address => struct IAbstractTokenConverter.ConversionConfig))", "numberOfBytes": "32", - "value": "t_mapping(t_address,t_struct(ConversionConfig)5478_storage)" + "value": "t_mapping(t_address,t_struct(ConversionConfig)5493_storage)" }, "t_mapping(t_address,t_mapping(t_address,t_uint256))": { "encoding": "mapping", @@ -2511,12 +2511,12 @@ "numberOfBytes": "32", "value": "t_mapping(t_address,t_uint256)" }, - "t_mapping(t_address,t_struct(ConversionConfig)5478_storage)": { + "t_mapping(t_address,t_struct(ConversionConfig)5493_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct IAbstractTokenConverter.ConversionConfig)", "numberOfBytes": "32", - "value": "t_struct(ConversionConfig)5478_storage" + "value": "t_struct(ConversionConfig)5493_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2525,12 +2525,12 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_struct(ConversionConfig)5478_storage": { + "t_struct(ConversionConfig)5493_storage": { "encoding": "inplace", "label": "struct IAbstractTokenConverter.ConversionConfig", "members": [ { - "astId": 5473, + "astId": 5488, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "incentive", "offset": 0, @@ -2538,12 +2538,12 @@ "type": "t_uint256" }, { - "astId": 5477, + "astId": 5492, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "conversionAccess", "offset": 0, "slot": "1", - "type": "t_enum(ConversionAccessibility)5470" + "type": "t_enum(ConversionAccessibility)5485" } ], "numberOfBytes": "64" diff --git a/deployments/bsctestnet/SingleTokenConverterImp.json b/deployments/bsctestnet/SingleTokenConverterImp.json index 1d5aa382..fab2e856 100644 --- a/deployments/bsctestnet/SingleTokenConverterImp.json +++ b/deployments/bsctestnet/SingleTokenConverterImp.json @@ -1,5 +1,5 @@ { - "address": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", + "address": "0x42Ec3Eb6F23460dFDfa3aE5688f3415CDfE0C6AD", "abi": [ { "inputs": [], @@ -1381,39 +1381,39 @@ "type": "function" } ], - "transactionHash": "0xba9a92fb7e9385bbebc2d54c39b4d53d3511b3e443abb0158ab09a03342c6f79", + "transactionHash": "0xa085acd2320dbe2723a87264b7e9ac76a424170a13a93701112656cd27b20bd3", "receipt": { "to": null, "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", - "transactionIndex": 0, - "gasUsed": "3634796", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000080000000000000000000010000000000000000000000000400000000000000000000000000000000000800000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x446e0df3da06877fbeded838f80f30a728834ebdba83c4fd0140eb7b87ace215", - "transactionHash": "0xba9a92fb7e9385bbebc2d54c39b4d53d3511b3e443abb0158ab09a03342c6f79", + "contractAddress": "0x42Ec3Eb6F23460dFDfa3aE5688f3415CDfE0C6AD", + "transactionIndex": 2, + "gasUsed": "3635848", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000020000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000010000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf8b5ca66a054916d04f0b9bfd96a15eacd271c3f137c265d0d5540b0f940c647", + "transactionHash": "0xa085acd2320dbe2723a87264b7e9ac76a424170a13a93701112656cd27b20bd3", "logs": [ { - "transactionIndex": 0, - "blockNumber": 37698228, - "transactionHash": "0xba9a92fb7e9385bbebc2d54c39b4d53d3511b3e443abb0158ab09a03342c6f79", - "address": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", + "transactionIndex": 2, + "blockNumber": 38131272, + "transactionHash": "0xa085acd2320dbe2723a87264b7e9ac76a424170a13a93701112656cd27b20bd3", + "address": "0x42Ec3Eb6F23460dFDfa3aE5688f3415CDfE0C6AD", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "logIndex": 0, - "blockHash": "0x446e0df3da06877fbeded838f80f30a728834ebdba83c4fd0140eb7b87ace215" + "logIndex": 4, + "blockHash": "0xf8b5ca66a054916d04f0b9bfd96a15eacd271c3f137c265d0d5540b0f940c647" } ], - "blockNumber": 37698228, - "cumulativeGasUsed": "3634796", + "blockNumber": 38131272, + "cumulativeGasUsed": "3844181", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 2, - "solcInputHash": "e9f683aad829bf9574e4eef6b067ab3e", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newBaseAsset\",\"type\":\"address\"}],\"name\":\"BaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"}],\"name\":\"setBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Balance of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256)\":{\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"baseAsset_\":\"Address of the base asset\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"Minimum amount to convert\",\"priceOracle_\":\"Resilient oracle address\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"baseAsset_\":\"The new address of the base asset\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"SingleTokenConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"BaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when base asset is updated\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"baseAsset()\":{\"notice\":\"Address of the base asset token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setBaseAsset(address)\":{\"notice\":\"Sets the base asset for the contract\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"SingleTokenConverter used for token conversions and sends received tokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/SingleTokenConverter.sol\":\"SingleTokenConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa =\\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\\n tokenInToOutConversion; //round-up\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa =\\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\\n (tokenOutUnderlyingPrice * EXP_SCALE);\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n\\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\\n converterNetwork.isTokenConverter(msg.sender);\\n if (isPrivateConversion) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n if (isPrivateConversion) {\\n amountInMantissa = (amountOutMantissa * EXP_SCALE) / tokenInToOutConversion;\\n } else {\\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\\n }\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n}\\n\",\"keccak256\":\"0xdecdaf378a5af7744557fc29495d6db49c6900be1b03bcb6faa2b3a23c9a5c59\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/SingleTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\n\\n/// @title SingleTokenConverter\\n/// @author Venus\\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract SingleTokenConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the base asset token\\n address public baseAsset;\\n\\n /// @notice Emitted when base asset is updated\\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param baseAsset_ Address of the base asset\\n /// @param minAmountToConvert_ Minimum amount to convert\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address baseAsset_,\\n uint256 minAmountToConvert_\\n ) public initializer {\\n _setBaseAsset(baseAsset_);\\n\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @notice Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:access Only Governance\\n function setBaseAsset(address baseAsset_) external onlyOwner {\\n _setBaseAsset(baseAsset_);\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n tokenBalance = token.balanceOf(address(this));\\n }\\n\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address.\\n /// @return balanceLeft Amount of asset, for _privateConversion\\n // solhint-disable-next-line\\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 balance = token.balanceOf(address(this));\\n balanceLeft = balance;\\n\\n if (asset == baseAsset) {\\n balanceLeft = 0;\\n token.safeTransfer(destinationAddress, balance);\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\\n }\\n }\\n\\n /// @dev Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n /// @custom:event BaseAssetUpdated is emitted on success\\n function _setBaseAsset(address baseAsset_) internal {\\n ensureNonzeroAddress(baseAsset_);\\n emit BaseAssetUpdated(baseAsset, baseAsset_);\\n baseAsset = baseAsset_;\\n }\\n\\n /// @dev Get base asset address\\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = baseAsset;\\n }\\n}\\n\",\"keccak256\":\"0x385804c4f8a1d5b0ed58da01f584c778e2a869b280ad6cb607b7fe8539c51897\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6140bf80620000f36000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d4366004613835565b610562565b005b6102ee6102e9366004613852565b610576565b60408051928352602083019190915201610288565b6102d9610311366004613835565b610624565b60fc54610274906001600160a01b031681565b6102d9610337366004613835565b610635565b6102ee61034a366004613894565b610646565b6102d961035d366004613835565b610784565b6102d9610370366004613835565b610795565b6102d96107a6565b6102ee61038b366004613852565b61088c565b6102d961039e3660046138f3565b610973565b6102ee6103b1366004613852565b610a10565b6102ee6103c4366004613852565b610b19565b6103dc6103d7366004613835565b610c18565b604051908152602001610288565b6102d9610ca5565b6102d9610400366004613934565b610cb9565b6102d9610d00565b6033546001600160a01b0316610274565b6102ee61042c366004613894565b610d90565b6102d961043f36600461394d565b610e7a565b61047961045236600461394d565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139f0565b6097546001600160a01b0316610274565b6102ee6104a6366004613894565b610eb0565b6102d9610f9a565b6102d96104c1366004613a50565b61104c565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613894565b6110ea565b6102d961052e366004613b04565b61120d565b6102d9610541366004613835565b6115ac565b6102d9610554366004613b75565b611635565b6103dc60fb5481565b61056a6117bf565b61057381611819565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b8613986565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610c18565b905085811015610608578095505b859250610616868686611896565b508092505050935093915050565b61062c6117bf565b61057381611bed565b61063d6117bf565b61057381611ce2565b600080828585610654611d61565b61065d83611db6565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611df6565b6106da8a8a8a8a8a611e4f565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117bf565b61057381611ed6565b61079d6117bf565b61057381611f53565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611fd0565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce613986565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b849150600061091586868661209c565b9092509050600061092585610c18565b9050828110156109695781600181610945670de0b6b3a764000085613c08565b61094f9190613c45565b6109599190613c5d565b6109639190613c74565b93508092505b5050935093915050565b61097b6117bf565b610983611df6565b61098c83611db6565b61099582611db6565b61099e816123bd565b826109b36001600160a01b03821684846123f7565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109f891815260200190565b60405180910390a350610a0b600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b50505050610b0f85858561209c565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b7d57600080fd5b505af1158015610b91573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bf557600080fd5b505af1158015610c09573d6000803e3d6000fd5b50505050610b0f858585611896565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9e9190613caf565b9392505050565b610cad6117bf565b610cb760006124be565b565b610cf76040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611fd0565b610573816124ef565b60655433906001600160a01b03168114610d875760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610573816124be565b600080828585610d9e611d61565b610da783611db6565b816001600160a01b0316836001600160a01b03161480610dd85750806001600160a01b0316836001600160a01b0316145b15610e0f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e17611df6565b610e248a8a8a8a8a611e4f565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e82611df6565b6000610e8e8383612539565b90508015610ea157610ea183838361264e565b50610eac600160c955565b5050565b600080828585610ebe611d61565b610ec783611db6565b816001600160a01b0316836001600160a01b03161480610ef85750806001600160a01b0316836001600160a01b0316145b15610f2f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f37611df6565b610f448a8a8a8a8a612b0b565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fd86040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611fd0565b610fe0611d61565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b82818114611086576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110e1576110d9878787848181106110a7576110a7613cc8565b90506020020160208101906110bc9190613835565b8686858181106110ce576110ce613cc8565b90506040020161120d565b600101611089565b50505050505050565b6000808285856110f8611d61565b61110183611db6565b816001600160a01b0316836001600160a01b031614806111325750806001600160a01b0316836001600160a01b0316145b15611169576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611171611df6565b61117e8a8a8a8a8a612b9d565b90955093508884146111bc576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61122e60405180606001604052806035815260200161405560359139611fd0565b61123783611db6565b61124082611db6565b6706f05b59d3b2000081351115611294576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d7e565b816001600160a01b0316836001600160a01b031614806112c3575061012d546001600160a01b03848116911614155b8061130b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561130857611308613986565b14155b15611342576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113546040830160208401613cf7565b600381111561136557611365613986565b1480156113725750803515155b156113a9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113bb6040830160208401613cf7565b60038111156113cc576113cc613986565b14806113f8575060016113e56040830160208401613cf7565b60038111156113f6576113f6613986565b145b801561140d575060ff546001600160a01b0316155b15611444576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff909116916114b491908a01908a01613cf7565b6040516114c49493929190613d18565b60405180910390a360006114de6040840160208501613cf7565b60038111156114ef576114ef613986565b0361154c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556115a6565b813581556115606040830160208401613cf7565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115a0576115a0613986565b02179055505b50505050565b6115b46117bf565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115fd6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff16158080156116555750600054600160ff909116105b8061166f5750303b15801561166f575060005460ff166001145b6116e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d7e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561173f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61174883611ce2565b61175486868685612c5a565b80156117b757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610cb75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d7e565b61182281611db6565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118d3576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561192757611927613986565b600381111561193857611938613986565b905250905060008160200151600381111561195557611955613986565b0361198c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a149190613caf565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613caf565b835160ff54919250906000906001600160a01b031615801590611b44575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b449190613d49565b90508015611b5157600091505b6000611b6583670de0b6b3a7640000613c45565b905083611b728287613c08565b611b7c9190613c74565b96508115611ba85786611b97670de0b6b3a76400008d613c08565b611ba19190613c74565b9750611bdf565b86600181611bbe670de0b6b3a76400008f613c08565b611bc89190613c45565b611bd29190613c5d565b611bdc9190613c74565b97505b505050505050935093915050565b6001600160a01b038116611c695760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d7e565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611ceb81611db6565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610cb7576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e485760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d7e565b600260c955565b600080611e5c8585612cf3565b611e668588612e13565b9150611e73828686610a10565b91505085811015611eba576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d7e565b611ec5848483612f5e565b9550959350505050565b600160c955565b611edf81611db6565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f5c81611db6565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab9061201c9033908690600401613de1565b602060405180830381865afa158015612039573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061205d9190613d49565b905080610eac573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d7e93929190613e03565b600080846000036120d9576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561212d5761212d613986565b600381111561213e5761213e613986565b905250905060008160200151600381111561215b5761215b613986565b03612192576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221a9190613caf565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612283573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a79190613caf565b835160ff54919250906001600160a01b031615801590612347575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612323573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123479190613d49565b15612350575060005b600061236482670de0b6b3a7640000613c45565b9050612378670de0b6b3a764000084613c08565b81612383868d613c08565b61238d9190613c08565b6123979190613c74565b9650826123a48286613c08565b6123ae9190613c74565b95505050505050935093915050565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610a0b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612fc1565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610573816130a9565b6124f8816123bd565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c19190613caf565b61012d549093508391506001600160a01b03908116908516036126465760fe54600093506125fc906001600160a01b038481169116836123f7565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061266361012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612b065760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126f2573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526127389190810190613f3c565b8151919350915060005b81811015612b015782818151811061275c5761275c613cc8565b602002602001015160000315612b0157600084828151811061278057612780613cc8565b60200260200101516001600160a01b0316636f1a30a88584815181106127a8576127a8613cc8565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127ea939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015612808573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282c9190614001565b9150508881111561283a5750875b612844818b613113565b61284e5750612b01565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa1580156128b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d59190613caf565b90508a6001600160a01b031663095ea7b38785815181106128f8576128f8613cc8565b6020026020010151846040518363ffffffff1660e01b81526004016129329291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015612951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129759190613d49565b5085838151811061298857612988613cc8565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015612a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a369190614001565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abf9190613caf565b9050612acb838c613c5d565b9a50612ad78282613c5d565b612ae19089613c45565b97508a600003612af357505050612b01565b836001019350505050612742565b505050505b6117b7565b600080612b188585612cf3565b6000612b25878787610b19565b91505087811115612b6c576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612b768682612e13565b9250612b83838787610a10565b9250612b929050858584612f5e565b509550959350505050565b600080612baa8585612cf3565b6000612bb7878787610b19565b915050612bc48682612e13565b9250808314612bff576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c43576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612c4e858589612f5e565b50909694955050505050565b600054610100900460ff16612cd75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b612ce08461324b565b612ce86132d9565b6115a683838361335e565b60ff546000906001600160a01b031615801590612d90575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d909190613d49565b905080158015612ddc575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612dda57612dda613986565b145b15610a0b576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea09190613caf565b60fe54909150612ebf906001600160a01b038481169133911687613423565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f489190613caf565b9050612f548282613c5d565b9695505050505050565b6000612f6984610c18565b905081811015612fa5576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612fba6001600160a01b03821685856123f7565b5050505050565b6000613016826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134749092919063ffffffff16565b90508051600014806130375750808060200190518101906130379190613d49565b610a0b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d7e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561317457600080fd5b505af1158015613188573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156131fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132209190613caf565b61322a9190613c08565b6132349190613c74565b905060fb54811061324457600191505b5092915050565b600054610100900460ff166132c85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6132d061348b565b61057381613510565b600054610100900460ff166133565760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb761358d565b600054610100900460ff166133db5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6133e483611f53565b6133ed82611819565b6133f6816124ef565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b03808516602483015283166044820152606481018290526115a69085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161243c565b6060613483848460008561360a565b949350505050565b600054610100900460ff166135085760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb76136fc565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b600054610100900460ff16611ecf5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6060824710156136825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d7e565b600080866001600160a01b0316858760405161369e9190614025565b60006040518083038185875af1925050503d80600081146136db576040519150601f19603f3d011682016040523d82523d6000602084013e6136e0565b606091505b50915091506136f187838387613782565b979650505050505050565b600054610100900460ff166137795760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb7336124be565b606083156137f15782516000036137ea576001600160a01b0385163b6137ea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d7e565b5081613483565b61348383838151156138065781518083602001fd5b8060405162461bcd60e51b8152600401610d7e9190614041565b6001600160a01b038116811461057357600080fd5b60006020828403121561384757600080fd5b8135610c9e81613820565b60008060006060848603121561386757600080fd5b83359250602084013561387981613820565b9150604084013561388981613820565b809150509250925092565b600080600080600060a086880312156138ac57600080fd5b853594506020860135935060408601356138c581613820565b925060608601356138d581613820565b915060808601356138e581613820565b809150509295509295909350565b60008060006060848603121561390857600080fd5b833561391381613820565b9250602084013561392381613820565b929592945050506040919091013590565b60006020828403121561394657600080fd5b5035919050565b6000806040838503121561396057600080fd5b823561396b81613820565b9150602083013561397b81613820565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c9e60208301846139b5565b60008083601f840112613a1657600080fd5b50813567ffffffffffffffff811115613a2e57600080fd5b6020830191508360208260061b8501011115613a4957600080fd5b9250929050565b600080600080600060608688031215613a6857600080fd5b8535613a7381613820565b9450602086013567ffffffffffffffff80821115613a9057600080fd5b818801915088601f830112613aa457600080fd5b813581811115613ab357600080fd5b8960208260051b8501011115613ac857600080fd5b602083019650809550506040880135915080821115613ae657600080fd5b50613af388828901613a04565b969995985093965092949392505050565b60008060008385036080811215613b1a57600080fd5b8435613b2581613820565b93506020850135613b3581613820565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b6757600080fd5b506040840190509250925092565b600080600080600060a08688031215613b8d57600080fd5b8535613b9881613820565b94506020860135613ba881613820565b93506040860135613bb881613820565b92506060860135613bc881613820565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c4057613c40613bd9565b500290565b60008219821115613c5857613c58613bd9565b500190565b600082821015613c6f57613c6f613bd9565b500390565b600082613caa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613cc157600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613d0957600080fd5b813560048110610c9e57600080fd5b8481526020810184905260808101613d3360408301856139b5565b613d4060608301846139b5565b95945050505050565b600060208284031215613d5b57600080fd5b81518015158114610c9e57600080fd5b60005b83811015613d86578181015183820152602001613d6e565b838111156115a65750506000910152565b60008151808452613daf816020860160208601613d6b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134836040830184613d97565b60006001600160a01b03808616835280851660208401525060606040830152613d406060830184613d97565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613ea557613ea5613e2f565b604052919050565b600067ffffffffffffffff821115613ec757613ec7613e2f565b5060051b60200190565b600082601f830112613ee257600080fd5b81516020613ef7613ef283613ead565b613e5e565b82815260059290921b84018101918181019086841115613f1657600080fd5b8286015b84811015613f315780518352918301918301613f1a565b509695505050505050565b60008060408385031215613f4f57600080fd5b825167ffffffffffffffff80821115613f6757600080fd5b818501915085601f830112613f7b57600080fd5b81516020613f8b613ef283613ead565b82815260059290921b84018101918181019089841115613faa57600080fd5b948201945b83861015613fd1578551613fc281613820565b82529482019490820190613faf565b91880151919650909350505080821115613fea57600080fd5b50613ff785828601613ed1565b9150509250929050565b6000806040838503121561401457600080fd5b505080516020909101519092909150565b60008251614037818460208701613d6b565b9190910192915050565b602081526000610c9e6020830184613d9756fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220a04acd5d02eeb8911e2a4fe28bd53f1481291334e654b0618600b13dc59cea2f64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d4366004613835565b610562565b005b6102ee6102e9366004613852565b610576565b60408051928352602083019190915201610288565b6102d9610311366004613835565b610624565b60fc54610274906001600160a01b031681565b6102d9610337366004613835565b610635565b6102ee61034a366004613894565b610646565b6102d961035d366004613835565b610784565b6102d9610370366004613835565b610795565b6102d96107a6565b6102ee61038b366004613852565b61088c565b6102d961039e3660046138f3565b610973565b6102ee6103b1366004613852565b610a10565b6102ee6103c4366004613852565b610b19565b6103dc6103d7366004613835565b610c18565b604051908152602001610288565b6102d9610ca5565b6102d9610400366004613934565b610cb9565b6102d9610d00565b6033546001600160a01b0316610274565b6102ee61042c366004613894565b610d90565b6102d961043f36600461394d565b610e7a565b61047961045236600461394d565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139f0565b6097546001600160a01b0316610274565b6102ee6104a6366004613894565b610eb0565b6102d9610f9a565b6102d96104c1366004613a50565b61104c565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613894565b6110ea565b6102d961052e366004613b04565b61120d565b6102d9610541366004613835565b6115ac565b6102d9610554366004613b75565b611635565b6103dc60fb5481565b61056a6117bf565b61057381611819565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b8613986565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610c18565b905085811015610608578095505b859250610616868686611896565b508092505050935093915050565b61062c6117bf565b61057381611bed565b61063d6117bf565b61057381611ce2565b600080828585610654611d61565b61065d83611db6565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611df6565b6106da8a8a8a8a8a611e4f565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117bf565b61057381611ed6565b61079d6117bf565b61057381611f53565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611fd0565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce613986565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b849150600061091586868661209c565b9092509050600061092585610c18565b9050828110156109695781600181610945670de0b6b3a764000085613c08565b61094f9190613c45565b6109599190613c5d565b6109639190613c74565b93508092505b5050935093915050565b61097b6117bf565b610983611df6565b61098c83611db6565b61099582611db6565b61099e816123bd565b826109b36001600160a01b03821684846123f7565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109f891815260200190565b60405180910390a350610a0b600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b50505050610b0f85858561209c565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b7d57600080fd5b505af1158015610b91573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bf557600080fd5b505af1158015610c09573d6000803e3d6000fd5b50505050610b0f858585611896565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9e9190613caf565b9392505050565b610cad6117bf565b610cb760006124be565b565b610cf76040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611fd0565b610573816124ef565b60655433906001600160a01b03168114610d875760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610573816124be565b600080828585610d9e611d61565b610da783611db6565b816001600160a01b0316836001600160a01b03161480610dd85750806001600160a01b0316836001600160a01b0316145b15610e0f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e17611df6565b610e248a8a8a8a8a611e4f565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e82611df6565b6000610e8e8383612539565b90508015610ea157610ea183838361264e565b50610eac600160c955565b5050565b600080828585610ebe611d61565b610ec783611db6565b816001600160a01b0316836001600160a01b03161480610ef85750806001600160a01b0316836001600160a01b0316145b15610f2f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f37611df6565b610f448a8a8a8a8a612b0b565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fd86040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611fd0565b610fe0611d61565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b82818114611086576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110e1576110d9878787848181106110a7576110a7613cc8565b90506020020160208101906110bc9190613835565b8686858181106110ce576110ce613cc8565b90506040020161120d565b600101611089565b50505050505050565b6000808285856110f8611d61565b61110183611db6565b816001600160a01b0316836001600160a01b031614806111325750806001600160a01b0316836001600160a01b0316145b15611169576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611171611df6565b61117e8a8a8a8a8a612b9d565b90955093508884146111bc576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61122e60405180606001604052806035815260200161405560359139611fd0565b61123783611db6565b61124082611db6565b6706f05b59d3b2000081351115611294576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d7e565b816001600160a01b0316836001600160a01b031614806112c3575061012d546001600160a01b03848116911614155b8061130b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561130857611308613986565b14155b15611342576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113546040830160208401613cf7565b600381111561136557611365613986565b1480156113725750803515155b156113a9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113bb6040830160208401613cf7565b60038111156113cc576113cc613986565b14806113f8575060016113e56040830160208401613cf7565b60038111156113f6576113f6613986565b145b801561140d575060ff546001600160a01b0316155b15611444576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff909116916114b491908a01908a01613cf7565b6040516114c49493929190613d18565b60405180910390a360006114de6040840160208501613cf7565b60038111156114ef576114ef613986565b0361154c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556115a6565b813581556115606040830160208401613cf7565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115a0576115a0613986565b02179055505b50505050565b6115b46117bf565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115fd6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff16158080156116555750600054600160ff909116105b8061166f5750303b15801561166f575060005460ff166001145b6116e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d7e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561173f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61174883611ce2565b61175486868685612c5a565b80156117b757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610cb75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d7e565b61182281611db6565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118d3576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561192757611927613986565b600381111561193857611938613986565b905250905060008160200151600381111561195557611955613986565b0361198c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a149190613caf565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613caf565b835160ff54919250906000906001600160a01b031615801590611b44575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b449190613d49565b90508015611b5157600091505b6000611b6583670de0b6b3a7640000613c45565b905083611b728287613c08565b611b7c9190613c74565b96508115611ba85786611b97670de0b6b3a76400008d613c08565b611ba19190613c74565b9750611bdf565b86600181611bbe670de0b6b3a76400008f613c08565b611bc89190613c45565b611bd29190613c5d565b611bdc9190613c74565b97505b505050505050935093915050565b6001600160a01b038116611c695760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d7e565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611ceb81611db6565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610cb7576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e485760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d7e565b600260c955565b600080611e5c8585612cf3565b611e668588612e13565b9150611e73828686610a10565b91505085811015611eba576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d7e565b611ec5848483612f5e565b9550959350505050565b600160c955565b611edf81611db6565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f5c81611db6565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab9061201c9033908690600401613de1565b602060405180830381865afa158015612039573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061205d9190613d49565b905080610eac573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d7e93929190613e03565b600080846000036120d9576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561212d5761212d613986565b600381111561213e5761213e613986565b905250905060008160200151600381111561215b5761215b613986565b03612192576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221a9190613caf565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612283573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a79190613caf565b835160ff54919250906001600160a01b031615801590612347575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612323573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123479190613d49565b15612350575060005b600061236482670de0b6b3a7640000613c45565b9050612378670de0b6b3a764000084613c08565b81612383868d613c08565b61238d9190613c08565b6123979190613c74565b9650826123a48286613c08565b6123ae9190613c74565b95505050505050935093915050565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610a0b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612fc1565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610573816130a9565b6124f8816123bd565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c19190613caf565b61012d549093508391506001600160a01b03908116908516036126465760fe54600093506125fc906001600160a01b038481169116836123f7565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061266361012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612b065760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126f2573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526127389190810190613f3c565b8151919350915060005b81811015612b015782818151811061275c5761275c613cc8565b602002602001015160000315612b0157600084828151811061278057612780613cc8565b60200260200101516001600160a01b0316636f1a30a88584815181106127a8576127a8613cc8565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127ea939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015612808573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282c9190614001565b9150508881111561283a5750875b612844818b613113565b61284e5750612b01565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa1580156128b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d59190613caf565b90508a6001600160a01b031663095ea7b38785815181106128f8576128f8613cc8565b6020026020010151846040518363ffffffff1660e01b81526004016129329291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015612951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129759190613d49565b5085838151811061298857612988613cc8565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015612a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a369190614001565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abf9190613caf565b9050612acb838c613c5d565b9a50612ad78282613c5d565b612ae19089613c45565b97508a600003612af357505050612b01565b836001019350505050612742565b505050505b6117b7565b600080612b188585612cf3565b6000612b25878787610b19565b91505087811115612b6c576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612b768682612e13565b9250612b83838787610a10565b9250612b929050858584612f5e565b509550959350505050565b600080612baa8585612cf3565b6000612bb7878787610b19565b915050612bc48682612e13565b9250808314612bff576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c43576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612c4e858589612f5e565b50909694955050505050565b600054610100900460ff16612cd75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b612ce08461324b565b612ce86132d9565b6115a683838361335e565b60ff546000906001600160a01b031615801590612d90575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d909190613d49565b905080158015612ddc575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612dda57612dda613986565b145b15610a0b576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea09190613caf565b60fe54909150612ebf906001600160a01b038481169133911687613423565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f489190613caf565b9050612f548282613c5d565b9695505050505050565b6000612f6984610c18565b905081811015612fa5576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612fba6001600160a01b03821685856123f7565b5050505050565b6000613016826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134749092919063ffffffff16565b90508051600014806130375750808060200190518101906130379190613d49565b610a0b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d7e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561317457600080fd5b505af1158015613188573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156131fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132209190613caf565b61322a9190613c08565b6132349190613c74565b905060fb54811061324457600191505b5092915050565b600054610100900460ff166132c85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6132d061348b565b61057381613510565b600054610100900460ff166133565760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb761358d565b600054610100900460ff166133db5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6133e483611f53565b6133ed82611819565b6133f6816124ef565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b03808516602483015283166044820152606481018290526115a69085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161243c565b6060613483848460008561360a565b949350505050565b600054610100900460ff166135085760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb76136fc565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b600054610100900460ff16611ecf5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6060824710156136825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d7e565b600080866001600160a01b0316858760405161369e9190614025565b60006040518083038185875af1925050503d80600081146136db576040519150601f19603f3d011682016040523d82523d6000602084013e6136e0565b606091505b50915091506136f187838387613782565b979650505050505050565b600054610100900460ff166137795760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb7336124be565b606083156137f15782516000036137ea576001600160a01b0385163b6137ea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d7e565b5081613483565b61348383838151156138065781518083602001fd5b8060405162461bcd60e51b8152600401610d7e9190614041565b6001600160a01b038116811461057357600080fd5b60006020828403121561384757600080fd5b8135610c9e81613820565b60008060006060848603121561386757600080fd5b83359250602084013561387981613820565b9150604084013561388981613820565b809150509250925092565b600080600080600060a086880312156138ac57600080fd5b853594506020860135935060408601356138c581613820565b925060608601356138d581613820565b915060808601356138e581613820565b809150509295509295909350565b60008060006060848603121561390857600080fd5b833561391381613820565b9250602084013561392381613820565b929592945050506040919091013590565b60006020828403121561394657600080fd5b5035919050565b6000806040838503121561396057600080fd5b823561396b81613820565b9150602083013561397b81613820565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c9e60208301846139b5565b60008083601f840112613a1657600080fd5b50813567ffffffffffffffff811115613a2e57600080fd5b6020830191508360208260061b8501011115613a4957600080fd5b9250929050565b600080600080600060608688031215613a6857600080fd5b8535613a7381613820565b9450602086013567ffffffffffffffff80821115613a9057600080fd5b818801915088601f830112613aa457600080fd5b813581811115613ab357600080fd5b8960208260051b8501011115613ac857600080fd5b602083019650809550506040880135915080821115613ae657600080fd5b50613af388828901613a04565b969995985093965092949392505050565b60008060008385036080811215613b1a57600080fd5b8435613b2581613820565b93506020850135613b3581613820565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b6757600080fd5b506040840190509250925092565b600080600080600060a08688031215613b8d57600080fd5b8535613b9881613820565b94506020860135613ba881613820565b93506040860135613bb881613820565b92506060860135613bc881613820565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c4057613c40613bd9565b500290565b60008219821115613c5857613c58613bd9565b500190565b600082821015613c6f57613c6f613bd9565b500390565b600082613caa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613cc157600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613d0957600080fd5b813560048110610c9e57600080fd5b8481526020810184905260808101613d3360408301856139b5565b613d4060608301846139b5565b95945050505050565b600060208284031215613d5b57600080fd5b81518015158114610c9e57600080fd5b60005b83811015613d86578181015183820152602001613d6e565b838111156115a65750506000910152565b60008151808452613daf816020860160208601613d6b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134836040830184613d97565b60006001600160a01b03808616835280851660208401525060606040830152613d406060830184613d97565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613ea557613ea5613e2f565b604052919050565b600067ffffffffffffffff821115613ec757613ec7613e2f565b5060051b60200190565b600082601f830112613ee257600080fd5b81516020613ef7613ef283613ead565b613e5e565b82815260059290921b84018101918181019086841115613f1657600080fd5b8286015b84811015613f315780518352918301918301613f1a565b509695505050505050565b60008060408385031215613f4f57600080fd5b825167ffffffffffffffff80821115613f6757600080fd5b818501915085601f830112613f7b57600080fd5b81516020613f8b613ef283613ead565b82815260059290921b84018101918181019089841115613faa57600080fd5b948201945b83861015613fd1578551613fc281613820565b82529482019490820190613faf565b91880151919650909350505080821115613fea57600080fd5b50613ff785828601613ed1565b9150509250929050565b6000806040838503121561401457600080fd5b505080516020909101519092909150565b60008251614037818460208701613d6b565b9190910192915050565b602081526000610c9e6020830184613d9756fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220a04acd5d02eeb8911e2a4fe28bd53f1481291334e654b0618600b13dc59cea2f64736f6c634300080d0033", + "numDeployments": 3, + "solcInputHash": "91b55240df7761b1edcdbbc6fc102117", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newBaseAsset\",\"type\":\"address\"}],\"name\":\"BaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"}],\"name\":\"setBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Balance of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256)\":{\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"baseAsset_\":\"Address of the base asset\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"Minimum amount to convert\",\"priceOracle_\":\"Resilient oracle address\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"baseAsset_\":\"The new address of the base asset\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"SingleTokenConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"BaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when base asset is updated\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"baseAsset()\":{\"notice\":\"Address of the base asset token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setBaseAsset(address)\":{\"notice\":\"Sets the base asset for the contract\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"SingleTokenConverter used for token conversions and sends received tokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/SingleTokenConverter.sol\":\"SingleTokenConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa = _divRoundingUp(maxTokenOutReserve * EXP_SCALE, tokenInToOutConversion);\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa = (amountInMantissa * tokenInToOutConversion) / (EXP_SCALE);\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n\\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\\n converterNetwork.isTokenConverter(msg.sender);\\n if (isPrivateConversion) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n if (isPrivateConversion) {\\n amountInMantissa =\\n (amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) /\\n (tokenInUnderlyingPrice * conversionWithIncentive);\\n } else {\\n amountInMantissa = _divRoundingUp(\\n amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE,\\n tokenInUnderlyingPrice * conversionWithIncentive\\n );\\n }\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n\\n /// @dev Performs division where the result is rounded up\\n /// @param numerator The numerator of the division operation\\n /// @param denominator The denominator of the division operation. Must be non-zero\\n /// @return The result of the division, rounded up\\n function _divRoundingUp(uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return (numerator + denominator - 1) / denominator;\\n }\\n}\\n\",\"keccak256\":\"0x3a55b64cf2b9fe6872bffa9eabfbeef0a836227a0e8b588d813ae856771a40e9\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/SingleTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\n\\n/// @title SingleTokenConverter\\n/// @author Venus\\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract SingleTokenConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the base asset token\\n address public baseAsset;\\n\\n /// @notice Emitted when base asset is updated\\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param baseAsset_ Address of the base asset\\n /// @param minAmountToConvert_ Minimum amount to convert\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address baseAsset_,\\n uint256 minAmountToConvert_\\n ) public initializer {\\n _setBaseAsset(baseAsset_);\\n\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @notice Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:access Only Governance\\n function setBaseAsset(address baseAsset_) external onlyOwner {\\n _setBaseAsset(baseAsset_);\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n tokenBalance = token.balanceOf(address(this));\\n }\\n\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address.\\n /// @return balanceLeft Amount of asset, for _privateConversion\\n // solhint-disable-next-line\\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 balance = token.balanceOf(address(this));\\n balanceLeft = balance;\\n\\n if (asset == baseAsset) {\\n balanceLeft = 0;\\n token.safeTransfer(destinationAddress, balance);\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\\n }\\n }\\n\\n /// @dev Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n /// @custom:event BaseAssetUpdated is emitted on success\\n function _setBaseAsset(address baseAsset_) internal {\\n ensureNonzeroAddress(baseAsset_);\\n emit BaseAssetUpdated(baseAsset, baseAsset_);\\n baseAsset = baseAsset_;\\n }\\n\\n /// @dev Get base asset address\\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = baseAsset;\\n }\\n}\\n\",\"keccak256\":\"0x385804c4f8a1d5b0ed58da01f584c778e2a869b280ad6cb607b7fe8539c51897\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6140c480620000f36000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d436600461383a565b610562565b005b6102ee6102e9366004613857565b610576565b60408051928352602083019190915201610288565b6102d961031136600461383a565b610624565b60fc54610274906001600160a01b031681565b6102d961033736600461383a565b610635565b6102ee61034a366004613899565b610646565b6102d961035d36600461383a565b610784565b6102d961037036600461383a565b610795565b6102d96107a6565b6102ee61038b366004613857565b61088c565b6102d961039e3660046138f8565b61095a565b6102ee6103b1366004613857565b6109f7565b6102ee6103c4366004613857565b610b00565b6103dc6103d736600461383a565b610bff565b604051908152602001610288565b6102d9610c8c565b6102d9610400366004613939565b610ca0565b6102d9610ce7565b6033546001600160a01b0316610274565b6102ee61042c366004613899565b610d77565b6102d961043f366004613952565b610e61565b610479610452366004613952565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139f5565b6097546001600160a01b0316610274565b6102ee6104a6366004613899565b610e97565b6102d9610f81565b6102d96104c1366004613a55565b611033565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613899565b6110d1565b6102d961052e366004613b09565b6111f4565b6102d961054136600461383a565b611593565b6102d9610554366004613b7a565b61161c565b6103dc60fb5481565b61056a6117a6565b61057381611800565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b861398b565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610bff565b905085811015610608578095505b85925061061686868661187d565b508092505050935093915050565b61062c6117a6565b61057381611be3565b61063d6117a6565b61057381611cd8565b600080828585610654611d57565b61065d83611dac565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611dec565b6106da8a8a8a8a8a611e45565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117a6565b61057381611ecc565b61079d6117a6565b61057381611f49565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611fc6565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce61398b565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610915868686612092565b9092509050600061092585610bff565b9050828110156109505761094a610944670de0b6b3a764000083613c0d565b8361239f565b93508092505b5050935093915050565b6109626117a6565b61096a611dec565b61097383611dac565b61097c82611dac565b610985816123c2565b8261099a6001600160a01b03821684846123fc565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109df91815260200190565b60405180910390a3506109f2600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a5b57600080fd5b505af1158015610a6f573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610ad357600080fd5b505af1158015610ae7573d6000803e3d6000fd5b50505050610af6858585612092565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b6457600080fd5b505af1158015610b78573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bdc57600080fd5b505af1158015610bf0573d6000803e3d6000fd5b50505050610af685858561187d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c859190613c4a565b9392505050565b610c946117a6565b610c9e60006124c3565b565b610cde6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611fc6565b610573816124f4565b60655433906001600160a01b03168114610d6e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610573816124c3565b600080828585610d85611d57565b610d8e83611dac565b816001600160a01b0316836001600160a01b03161480610dbf5750806001600160a01b0316836001600160a01b0316145b15610df6576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfe611dec565b610e0b8a8a8a8a8a611e45565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e69611dec565b6000610e75838361253e565b90508015610e8857610e88838383612653565b50610e93600160c955565b5050565b600080828585610ea5611d57565b610eae83611dac565b816001600160a01b0316836001600160a01b03161480610edf5750806001600160a01b0316836001600160a01b0316145b15610f16576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1e611dec565b610f2b8a8a8a8a8a612b10565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fbf6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611fc6565b610fc7611d57565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b8281811461106d576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110c8576110c08787878481811061108e5761108e613c63565b90506020020160208101906110a3919061383a565b8686858181106110b5576110b5613c63565b9050604002016111f4565b600101611070565b50505050505050565b6000808285856110df611d57565b6110e883611dac565b816001600160a01b0316836001600160a01b031614806111195750806001600160a01b0316836001600160a01b0316145b15611150576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611158611dec565b6111658a8a8a8a8a612ba2565b90955093508884146111a3576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61121560405180606001604052806035815260200161405a60359139611fc6565b61121e83611dac565b61122782611dac565b6706f05b59d3b200008135111561127b576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d65565b816001600160a01b0316836001600160a01b031614806112aa575061012d546001600160a01b03848116911614155b806112f2575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff1660038111156112ef576112ef61398b565b14155b15611329576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261133b6040830160208401613c92565b600381111561134c5761134c61398b565b1480156113595750803515155b15611390576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113a26040830160208401613c92565b60038111156113b3576113b361398b565b14806113df575060016113cc6040830160208401613c92565b60038111156113dd576113dd61398b565b145b80156113f4575060ff546001600160a01b0316155b1561142b576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff9091169161149b91908a01908a01613c92565b6040516114ab9493929190613cb3565b60405180910390a360006114c56040840160208501613c92565b60038111156114d6576114d661398b565b03611533576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905561158d565b813581556115476040830160208401613c92565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115875761158761398b565b02179055505b50505050565b61159b6117a6565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115e46033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff161580801561163c5750600054600160ff909116105b806116565750303b158015611656575060005460ff166001145b6116c85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d65565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561172657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61172f83611cd8565b61173b86868685612c5f565b801561179e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610c9e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d65565b61180981611dac565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118ba576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561190e5761190e61398b565b600381111561191f5761191f61398b565b905250905060008160200151600381111561193c5761193c61398b565b03611973576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fb9190613c4a565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a889190613c4a565b835160ff54919250906000906001600160a01b031615801590611b2b575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2b9190613ce4565b90508015611b3857600091505b6000611b4c83670de0b6b3a7640000613d06565b90508115611b8c57611b5e8186613c0d565b670de0b6b3a7640000611b71868e613c0d565b611b7b9190613c0d565b611b859190613d1e565b9750611bbe565b611bbb670de0b6b3a7640000611ba2868e613c0d565b611bac9190613c0d565b611bb68388613c0d565b61239f565b97505b83611bc98287613c0d565b611bd39190613d1e565b9650505050505050935093915050565b6001600160a01b038116611c5f5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d65565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611ce181611dac565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610c9e576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e3e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d65565b600260c955565b600080611e528585612cf8565b611e5c8588612e18565b9150611e698286866109f7565b91505085811015611eb0576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d65565b611ebb848483612f63565b9550959350505050565b600160c955565b611ed581611dac565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f5281611dac565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906120129033908690600401613dcf565b602060405180830381865afa15801561202f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120539190613ce4565b905080610e93573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d6593929190613df1565b600080846000036120cf576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff1660038111156121235761212361398b565b60038111156121345761213461398b565b90525090506000816020015160038111156121515761215161398b565b03612188576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122109190613c4a565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612279573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229d9190613c4a565b835160ff54919250906001600160a01b03161580159061233d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061233d9190613ce4565b15612346575060005b600061235a82670de0b6b3a7640000613d06565b9050826123678286613c0d565b6123719190613d1e565b9550670de0b6b3a7640000612386878c613c0d565b6123909190613d1e565b96505050505050935093915050565b60008160016123ae8286613d06565b6123b89190613e1d565b610c859190613d1e565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b0383166024820152604481018290526109f29084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612fc6565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610573816130ae565b6124fd816123c2565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa1580156125a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c69190613c4a565b61012d549093508391506001600160a01b039081169085160361264b5760fe5460009350612601906001600160a01b038481169116836123fc565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061266861012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612b0b5760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261273d9190810190613f41565b8151919350915060005b81811015612b065782818151811061276157612761613c63565b602002602001015160000315612b0657600084828151811061278557612785613c63565b60200260200101516001600160a01b0316636f1a30a88584815181106127ad576127ad613c63565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127ef939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af115801561280d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128319190614006565b9150508881111561283f5750875b612849818b613118565b6128535750612b06565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa1580156128b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128da9190613c4a565b90508a6001600160a01b031663095ea7b38785815181106128fd576128fd613c63565b6020026020010151846040518363ffffffff1660e01b81526004016129379291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015612956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297a9190613ce4565b5085838151811061298d5761298d613c63565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015612a17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a3b9190614006565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac49190613c4a565b9050612ad0838c613e1d565b9a50612adc8282613e1d565b612ae69089613d06565b97508a600003612af857505050612b06565b836001019350505050612747565b505050505b61179e565b600080612b1d8585612cf8565b6000612b2a878787610b00565b91505087811115612b71576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d65565b612b7b8682612e18565b9250612b888387876109f7565b9250612b979050858584612f63565b509550959350505050565b600080612baf8585612cf8565b6000612bbc878787610b00565b915050612bc98682612e18565b9250808314612c04576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c48576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d65565b612c53858589612f63565b50909694955050505050565b600054610100900460ff16612cdc5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b612ce584613250565b612ced6132de565b61158d838383613363565b60ff546000906001600160a01b031615801590612d95575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d959190613ce4565b905080158015612de1575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612ddf57612ddf61398b565b145b156109f2576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea59190613c4a565b60fe54909150612ec4906001600160a01b038481169133911687613428565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612f29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f4d9190613c4a565b9050612f598282613e1d565b9695505050505050565b6000612f6e84610bff565b905081811015612faa576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612fbf6001600160a01b03821685856123fc565b5050505050565b600061301b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134799092919063ffffffff16565b905080516000148061303c57508080602001905181019061303c9190613ce4565b6109f25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d65565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561317957600080fd5b505af115801561318d573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa158015613201573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132259190613c4a565b61322f9190613c0d565b6132399190613d1e565b905060fb54811061324957600191505b5092915050565b600054610100900460ff166132cd5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6132d5613490565b61057381613515565b600054610100900460ff1661335b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e613592565b600054610100900460ff166133e05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6133e983611f49565b6133f282611800565b6133fb816124f4565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b038085166024830152831660448201526064810182905261158d9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612441565b6060613488848460008561360f565b949350505050565b600054610100900460ff1661350d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e613701565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b600054610100900460ff16611ec55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6060824710156136875760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d65565b600080866001600160a01b031685876040516136a3919061402a565b60006040518083038185875af1925050503d80600081146136e0576040519150601f19603f3d011682016040523d82523d6000602084013e6136e5565b606091505b50915091506136f687838387613787565b979650505050505050565b600054610100900460ff1661377e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e336124c3565b606083156137f65782516000036137ef576001600160a01b0385163b6137ef5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d65565b5081613488565b613488838381511561380b5781518083602001fd5b8060405162461bcd60e51b8152600401610d659190614046565b6001600160a01b038116811461057357600080fd5b60006020828403121561384c57600080fd5b8135610c8581613825565b60008060006060848603121561386c57600080fd5b83359250602084013561387e81613825565b9150604084013561388e81613825565b809150509250925092565b600080600080600060a086880312156138b157600080fd5b853594506020860135935060408601356138ca81613825565b925060608601356138da81613825565b915060808601356138ea81613825565b809150509295509295909350565b60008060006060848603121561390d57600080fd5b833561391881613825565b9250602084013561392881613825565b929592945050506040919091013590565b60006020828403121561394b57600080fd5b5035919050565b6000806040838503121561396557600080fd5b823561397081613825565b9150602083013561398081613825565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139f1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c8560208301846139ba565b60008083601f840112613a1b57600080fd5b50813567ffffffffffffffff811115613a3357600080fd5b6020830191508360208260061b8501011115613a4e57600080fd5b9250929050565b600080600080600060608688031215613a6d57600080fd5b8535613a7881613825565b9450602086013567ffffffffffffffff80821115613a9557600080fd5b818801915088601f830112613aa957600080fd5b813581811115613ab857600080fd5b8960208260051b8501011115613acd57600080fd5b602083019650809550506040880135915080821115613aeb57600080fd5b50613af888828901613a09565b969995985093965092949392505050565b60008060008385036080811215613b1f57600080fd5b8435613b2a81613825565b93506020850135613b3a81613825565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b6c57600080fd5b506040840190509250925092565b600080600080600060a08688031215613b9257600080fd5b8535613b9d81613825565b94506020860135613bad81613825565b93506040860135613bbd81613825565b92506060860135613bcd81613825565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c4557613c45613bde565b500290565b600060208284031215613c5c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613ca457600080fd5b813560048110610c8557600080fd5b8481526020810184905260808101613cce60408301856139ba565b613cdb60608301846139ba565b95945050505050565b600060208284031215613cf657600080fd5b81518015158114610c8557600080fd5b60008219821115613d1957613d19613bde565b500190565b600082613d54577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613d74578181015183820152602001613d5c565b8381111561158d5750506000910152565b60008151808452613d9d816020860160208601613d59565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134886040830184613d85565b60006001600160a01b03808616835280851660208401525060606040830152613cdb6060830184613d85565b600082821015613e2f57613e2f613bde565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613eaa57613eaa613e34565b604052919050565b600067ffffffffffffffff821115613ecc57613ecc613e34565b5060051b60200190565b600082601f830112613ee757600080fd5b81516020613efc613ef783613eb2565b613e63565b82815260059290921b84018101918181019086841115613f1b57600080fd5b8286015b84811015613f365780518352918301918301613f1f565b509695505050505050565b60008060408385031215613f5457600080fd5b825167ffffffffffffffff80821115613f6c57600080fd5b818501915085601f830112613f8057600080fd5b81516020613f90613ef783613eb2565b82815260059290921b84018101918181019089841115613faf57600080fd5b948201945b83861015613fd6578551613fc781613825565b82529482019490820190613fb4565b91880151919650909350505080821115613fef57600080fd5b50613ffc85828601613ed6565b9150509250929050565b6000806040838503121561401957600080fd5b505080516020909101519092909150565b6000825161403c818460208701613d59565b9190910192915050565b602081526000610c856020830184613d8556fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220c90768b57d16a90270136f659c9003d1890ce1f6dcc427a5e56b6e83cfbf87c164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d436600461383a565b610562565b005b6102ee6102e9366004613857565b610576565b60408051928352602083019190915201610288565b6102d961031136600461383a565b610624565b60fc54610274906001600160a01b031681565b6102d961033736600461383a565b610635565b6102ee61034a366004613899565b610646565b6102d961035d36600461383a565b610784565b6102d961037036600461383a565b610795565b6102d96107a6565b6102ee61038b366004613857565b61088c565b6102d961039e3660046138f8565b61095a565b6102ee6103b1366004613857565b6109f7565b6102ee6103c4366004613857565b610b00565b6103dc6103d736600461383a565b610bff565b604051908152602001610288565b6102d9610c8c565b6102d9610400366004613939565b610ca0565b6102d9610ce7565b6033546001600160a01b0316610274565b6102ee61042c366004613899565b610d77565b6102d961043f366004613952565b610e61565b610479610452366004613952565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139f5565b6097546001600160a01b0316610274565b6102ee6104a6366004613899565b610e97565b6102d9610f81565b6102d96104c1366004613a55565b611033565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613899565b6110d1565b6102d961052e366004613b09565b6111f4565b6102d961054136600461383a565b611593565b6102d9610554366004613b7a565b61161c565b6103dc60fb5481565b61056a6117a6565b61057381611800565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b861398b565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610bff565b905085811015610608578095505b85925061061686868661187d565b508092505050935093915050565b61062c6117a6565b61057381611be3565b61063d6117a6565b61057381611cd8565b600080828585610654611d57565b61065d83611dac565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611dec565b6106da8a8a8a8a8a611e45565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117a6565b61057381611ecc565b61079d6117a6565b61057381611f49565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611fc6565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce61398b565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610915868686612092565b9092509050600061092585610bff565b9050828110156109505761094a610944670de0b6b3a764000083613c0d565b8361239f565b93508092505b5050935093915050565b6109626117a6565b61096a611dec565b61097383611dac565b61097c82611dac565b610985816123c2565b8261099a6001600160a01b03821684846123fc565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109df91815260200190565b60405180910390a3506109f2600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a5b57600080fd5b505af1158015610a6f573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610ad357600080fd5b505af1158015610ae7573d6000803e3d6000fd5b50505050610af6858585612092565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b6457600080fd5b505af1158015610b78573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bdc57600080fd5b505af1158015610bf0573d6000803e3d6000fd5b50505050610af685858561187d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c859190613c4a565b9392505050565b610c946117a6565b610c9e60006124c3565b565b610cde6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611fc6565b610573816124f4565b60655433906001600160a01b03168114610d6e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610573816124c3565b600080828585610d85611d57565b610d8e83611dac565b816001600160a01b0316836001600160a01b03161480610dbf5750806001600160a01b0316836001600160a01b0316145b15610df6576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfe611dec565b610e0b8a8a8a8a8a611e45565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e69611dec565b6000610e75838361253e565b90508015610e8857610e88838383612653565b50610e93600160c955565b5050565b600080828585610ea5611d57565b610eae83611dac565b816001600160a01b0316836001600160a01b03161480610edf5750806001600160a01b0316836001600160a01b0316145b15610f16576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1e611dec565b610f2b8a8a8a8a8a612b10565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fbf6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611fc6565b610fc7611d57565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b8281811461106d576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110c8576110c08787878481811061108e5761108e613c63565b90506020020160208101906110a3919061383a565b8686858181106110b5576110b5613c63565b9050604002016111f4565b600101611070565b50505050505050565b6000808285856110df611d57565b6110e883611dac565b816001600160a01b0316836001600160a01b031614806111195750806001600160a01b0316836001600160a01b0316145b15611150576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611158611dec565b6111658a8a8a8a8a612ba2565b90955093508884146111a3576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61121560405180606001604052806035815260200161405a60359139611fc6565b61121e83611dac565b61122782611dac565b6706f05b59d3b200008135111561127b576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d65565b816001600160a01b0316836001600160a01b031614806112aa575061012d546001600160a01b03848116911614155b806112f2575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff1660038111156112ef576112ef61398b565b14155b15611329576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261133b6040830160208401613c92565b600381111561134c5761134c61398b565b1480156113595750803515155b15611390576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113a26040830160208401613c92565b60038111156113b3576113b361398b565b14806113df575060016113cc6040830160208401613c92565b60038111156113dd576113dd61398b565b145b80156113f4575060ff546001600160a01b0316155b1561142b576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff9091169161149b91908a01908a01613c92565b6040516114ab9493929190613cb3565b60405180910390a360006114c56040840160208501613c92565b60038111156114d6576114d661398b565b03611533576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905561158d565b813581556115476040830160208401613c92565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115875761158761398b565b02179055505b50505050565b61159b6117a6565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115e46033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff161580801561163c5750600054600160ff909116105b806116565750303b158015611656575060005460ff166001145b6116c85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d65565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561172657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61172f83611cd8565b61173b86868685612c5f565b801561179e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610c9e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d65565b61180981611dac565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118ba576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561190e5761190e61398b565b600381111561191f5761191f61398b565b905250905060008160200151600381111561193c5761193c61398b565b03611973576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fb9190613c4a565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a889190613c4a565b835160ff54919250906000906001600160a01b031615801590611b2b575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2b9190613ce4565b90508015611b3857600091505b6000611b4c83670de0b6b3a7640000613d06565b90508115611b8c57611b5e8186613c0d565b670de0b6b3a7640000611b71868e613c0d565b611b7b9190613c0d565b611b859190613d1e565b9750611bbe565b611bbb670de0b6b3a7640000611ba2868e613c0d565b611bac9190613c0d565b611bb68388613c0d565b61239f565b97505b83611bc98287613c0d565b611bd39190613d1e565b9650505050505050935093915050565b6001600160a01b038116611c5f5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d65565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611ce181611dac565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610c9e576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e3e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d65565b600260c955565b600080611e528585612cf8565b611e5c8588612e18565b9150611e698286866109f7565b91505085811015611eb0576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d65565b611ebb848483612f63565b9550959350505050565b600160c955565b611ed581611dac565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f5281611dac565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906120129033908690600401613dcf565b602060405180830381865afa15801561202f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120539190613ce4565b905080610e93573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d6593929190613df1565b600080846000036120cf576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff1660038111156121235761212361398b565b60038111156121345761213461398b565b90525090506000816020015160038111156121515761215161398b565b03612188576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122109190613c4a565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612279573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229d9190613c4a565b835160ff54919250906001600160a01b03161580159061233d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061233d9190613ce4565b15612346575060005b600061235a82670de0b6b3a7640000613d06565b9050826123678286613c0d565b6123719190613d1e565b9550670de0b6b3a7640000612386878c613c0d565b6123909190613d1e565b96505050505050935093915050565b60008160016123ae8286613d06565b6123b89190613e1d565b610c859190613d1e565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b0383166024820152604481018290526109f29084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612fc6565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610573816130ae565b6124fd816123c2565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa1580156125a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c69190613c4a565b61012d549093508391506001600160a01b039081169085160361264b5760fe5460009350612601906001600160a01b038481169116836123fc565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061266861012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612b0b5760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261273d9190810190613f41565b8151919350915060005b81811015612b065782818151811061276157612761613c63565b602002602001015160000315612b0657600084828151811061278557612785613c63565b60200260200101516001600160a01b0316636f1a30a88584815181106127ad576127ad613c63565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127ef939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af115801561280d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128319190614006565b9150508881111561283f5750875b612849818b613118565b6128535750612b06565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa1580156128b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128da9190613c4a565b90508a6001600160a01b031663095ea7b38785815181106128fd576128fd613c63565b6020026020010151846040518363ffffffff1660e01b81526004016129379291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015612956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297a9190613ce4565b5085838151811061298d5761298d613c63565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015612a17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a3b9190614006565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac49190613c4a565b9050612ad0838c613e1d565b9a50612adc8282613e1d565b612ae69089613d06565b97508a600003612af857505050612b06565b836001019350505050612747565b505050505b61179e565b600080612b1d8585612cf8565b6000612b2a878787610b00565b91505087811115612b71576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d65565b612b7b8682612e18565b9250612b888387876109f7565b9250612b979050858584612f63565b509550959350505050565b600080612baf8585612cf8565b6000612bbc878787610b00565b915050612bc98682612e18565b9250808314612c04576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c48576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d65565b612c53858589612f63565b50909694955050505050565b600054610100900460ff16612cdc5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b612ce584613250565b612ced6132de565b61158d838383613363565b60ff546000906001600160a01b031615801590612d95575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d959190613ce4565b905080158015612de1575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612ddf57612ddf61398b565b145b156109f2576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea59190613c4a565b60fe54909150612ec4906001600160a01b038481169133911687613428565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612f29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f4d9190613c4a565b9050612f598282613e1d565b9695505050505050565b6000612f6e84610bff565b905081811015612faa576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612fbf6001600160a01b03821685856123fc565b5050505050565b600061301b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134799092919063ffffffff16565b905080516000148061303c57508080602001905181019061303c9190613ce4565b6109f25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d65565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561317957600080fd5b505af115801561318d573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa158015613201573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132259190613c4a565b61322f9190613c0d565b6132399190613d1e565b905060fb54811061324957600191505b5092915050565b600054610100900460ff166132cd5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6132d5613490565b61057381613515565b600054610100900460ff1661335b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e613592565b600054610100900460ff166133e05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6133e983611f49565b6133f282611800565b6133fb816124f4565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b038085166024830152831660448201526064810182905261158d9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612441565b6060613488848460008561360f565b949350505050565b600054610100900460ff1661350d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e613701565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b600054610100900460ff16611ec55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6060824710156136875760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d65565b600080866001600160a01b031685876040516136a3919061402a565b60006040518083038185875af1925050503d80600081146136e0576040519150601f19603f3d011682016040523d82523d6000602084013e6136e5565b606091505b50915091506136f687838387613787565b979650505050505050565b600054610100900460ff1661377e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e336124c3565b606083156137f65782516000036137ef576001600160a01b0385163b6137ef5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d65565b5081613488565b613488838381511561380b5781518083602001fd5b8060405162461bcd60e51b8152600401610d659190614046565b6001600160a01b038116811461057357600080fd5b60006020828403121561384c57600080fd5b8135610c8581613825565b60008060006060848603121561386c57600080fd5b83359250602084013561387e81613825565b9150604084013561388e81613825565b809150509250925092565b600080600080600060a086880312156138b157600080fd5b853594506020860135935060408601356138ca81613825565b925060608601356138da81613825565b915060808601356138ea81613825565b809150509295509295909350565b60008060006060848603121561390d57600080fd5b833561391881613825565b9250602084013561392881613825565b929592945050506040919091013590565b60006020828403121561394b57600080fd5b5035919050565b6000806040838503121561396557600080fd5b823561397081613825565b9150602083013561398081613825565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139f1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c8560208301846139ba565b60008083601f840112613a1b57600080fd5b50813567ffffffffffffffff811115613a3357600080fd5b6020830191508360208260061b8501011115613a4e57600080fd5b9250929050565b600080600080600060608688031215613a6d57600080fd5b8535613a7881613825565b9450602086013567ffffffffffffffff80821115613a9557600080fd5b818801915088601f830112613aa957600080fd5b813581811115613ab857600080fd5b8960208260051b8501011115613acd57600080fd5b602083019650809550506040880135915080821115613aeb57600080fd5b50613af888828901613a09565b969995985093965092949392505050565b60008060008385036080811215613b1f57600080fd5b8435613b2a81613825565b93506020850135613b3a81613825565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b6c57600080fd5b506040840190509250925092565b600080600080600060a08688031215613b9257600080fd5b8535613b9d81613825565b94506020860135613bad81613825565b93506040860135613bbd81613825565b92506060860135613bcd81613825565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c4557613c45613bde565b500290565b600060208284031215613c5c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613ca457600080fd5b813560048110610c8557600080fd5b8481526020810184905260808101613cce60408301856139ba565b613cdb60608301846139ba565b95945050505050565b600060208284031215613cf657600080fd5b81518015158114610c8557600080fd5b60008219821115613d1957613d19613bde565b500190565b600082613d54577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613d74578181015183820152602001613d5c565b8381111561158d5750506000910152565b60008151808452613d9d816020860160208601613d59565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134886040830184613d85565b60006001600160a01b03808616835280851660208401525060606040830152613cdb6060830184613d85565b600082821015613e2f57613e2f613bde565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613eaa57613eaa613e34565b604052919050565b600067ffffffffffffffff821115613ecc57613ecc613e34565b5060051b60200190565b600082601f830112613ee757600080fd5b81516020613efc613ef783613eb2565b613e63565b82815260059290921b84018101918181019086841115613f1b57600080fd5b8286015b84811015613f365780518352918301918301613f1f565b509695505050505050565b60008060408385031215613f5457600080fd5b825167ffffffffffffffff80821115613f6c57600080fd5b818501915085601f830112613f8057600080fd5b81516020613f90613ef783613eb2565b82815260059290921b84018101918181019089841115613faf57600080fd5b948201945b83861015613fd6578551613fc781613825565b82529482019490820190613fb4565b91880151919650909350505080821115613fef57600080fd5b50613ffc85828601613ed6565b9150509250929050565b6000806040838503121561401957600080fd5b505080516020909101519092909150565b6000825161403c818460208701613d59565b9190910192915050565b602081526000610c856020830184613d8556fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220c90768b57d16a90270136f659c9003d1890ce1f6dcc427a5e56b6e83cfbf87c164736f6c634300080d0033", "devdoc": { "author": "Venus", "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", @@ -2021,7 +2021,7 @@ "label": "conversionConfigurations", "offset": 0, "slot": "253", - "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5478_storage))" + "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5493_storage))" }, { "astId": 3371, @@ -2056,7 +2056,7 @@ "type": "t_array(t_uint256)45_storage" }, { - "astId": 6828, + "astId": 6843, "contract": "contracts/TokenConverter/SingleTokenConverter.sol:SingleTokenConverter", "label": "baseAsset", "offset": 0, @@ -2108,31 +2108,31 @@ "label": "contract ResilientOracle", "numberOfBytes": "20" }, - "t_enum(ConversionAccessibility)5470": { + "t_enum(ConversionAccessibility)5485": { "encoding": "inplace", "label": "enum IAbstractTokenConverter.ConversionAccessibility", "numberOfBytes": "1" }, - "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5478_storage))": { + "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5493_storage))": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => mapping(address => struct IAbstractTokenConverter.ConversionConfig))", "numberOfBytes": "32", - "value": "t_mapping(t_address,t_struct(ConversionConfig)5478_storage)" + "value": "t_mapping(t_address,t_struct(ConversionConfig)5493_storage)" }, - "t_mapping(t_address,t_struct(ConversionConfig)5478_storage)": { + "t_mapping(t_address,t_struct(ConversionConfig)5493_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct IAbstractTokenConverter.ConversionConfig)", "numberOfBytes": "32", - "value": "t_struct(ConversionConfig)5478_storage" + "value": "t_struct(ConversionConfig)5493_storage" }, - "t_struct(ConversionConfig)5478_storage": { + "t_struct(ConversionConfig)5493_storage": { "encoding": "inplace", "label": "struct IAbstractTokenConverter.ConversionConfig", "members": [ { - "astId": 5473, + "astId": 5488, "contract": "contracts/TokenConverter/SingleTokenConverter.sol:SingleTokenConverter", "label": "incentive", "offset": 0, @@ -2140,12 +2140,12 @@ "type": "t_uint256" }, { - "astId": 5477, + "astId": 5492, "contract": "contracts/TokenConverter/SingleTokenConverter.sol:SingleTokenConverter", "label": "conversionAccess", "offset": 0, "slot": "1", - "type": "t_enum(ConversionAccessibility)5470" + "type": "t_enum(ConversionAccessibility)5485" } ], "numberOfBytes": "64" diff --git a/deployments/bsctestnet/solcInputs/91b55240df7761b1edcdbbc6fc102117.json b/deployments/bsctestnet/solcInputs/91b55240df7761b1edcdbbc6fc102117.json new file mode 100644 index 00000000..e5ccd92a --- /dev/null +++ b/deployments/bsctestnet/solcInputs/91b55240df7761b1edcdbbc6fc102117.json @@ -0,0 +1,123 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides 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} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling 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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\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.9.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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlledV8\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\n /// @notice Access control manager contract\n IAccessControlManagerV8 private _accessControlManager;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when access control manager contract address is changed\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n /// @notice Thrown when the action is prohibited by AccessControlManager\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Sets the address of AccessControlManager\n * @dev Admin function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n * @custom:event Emits NewAccessControlManager event\n * @custom:access Only Governance\n */\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Returns the address of the access control manager contract\n */\n function accessControlManager() external view returns (IAccessControlManagerV8) {\n return _accessControlManager;\n }\n\n /**\n * @dev Internal function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n */\n function _setAccessControlManager(address accessControlManager_) internal {\n require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n address oldAccessControlManager = address(_accessControlManager);\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title IAccessControlManagerV8\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\n */\ninterface IAccessControlManagerV8 is IAccessControl {\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) external;\n\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface OracleInterface {\n function getPrice(address asset) external view returns (uint256);\n}\n\ninterface ResilientOracleInterface is OracleInterface {\n function updatePrice(address vToken) external;\n\n function updateAssetPrice(address asset) external;\n\n function getUnderlyingPrice(address vToken) external view returns (uint256);\n}\n\ninterface TwapInterface is OracleInterface {\n function updateTwap(address asset) external returns (uint256);\n}\n\ninterface BoundValidatorInterface {\n function validatePriceWithAnchorPrice(\n address asset,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface VBep20Interface is IERC20Metadata {\n /**\n * @notice Underlying asset for this VToken\n */\n function underlying() external view returns (address);\n}\n" + }, + "@venusprotocol/oracle/contracts/ResilientOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"./interfaces/VBep20Interface.sol\";\nimport \"./interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ResilientOracle\n * @author Venus\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\n * \n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\n * for attacking the protocol.\n * \n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\n * \n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \n * \n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\n * market. The upper bound ratio represents the deviation between reported price (the price that’s being\n * validated) and the anchor price (the price we are validating against) above which the reported price will\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\n * should be true:\n\n```\nanchorRatio = anchorPrice/reporterPrice\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\n```\n\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \n * \n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\n * oracle to be stagnant and treat it like it's disabled.\n */\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\n /**\n * @dev Oracle roles:\n * **main**: The most trustworthy price source\n * **pivot**: Price oracle used as a loose sanity checker\n * **fallback**: The backup source when main oracle price is invalidated\n */\n enum OracleRole {\n MAIN,\n PIVOT,\n FALLBACK\n }\n\n struct TokenConfig {\n /// @notice asset address\n address asset;\n /// @notice `oracles` stores the oracles based on their role in the following order:\n /// [main, pivot, fallback],\n /// It can be indexed with the corresponding enum OracleRole value\n address[3] oracles;\n /// @notice `enableFlagsForOracles` stores the enabled state\n /// for each oracle in the same order as `oracles`\n bool[3] enableFlagsForOracles;\n }\n\n uint256 public constant INVALID_PRICE = 0;\n\n /// @notice Native market address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable nativeMarket;\n\n /// @notice VAI address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vai;\n\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\n /// and can serve as any underlying asset of a market that supports native tokens\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Bound validator contract address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n BoundValidatorInterface public immutable boundValidator;\n\n mapping(address => TokenConfig) private tokenConfigs;\n\n event TokenConfigAdded(\n address indexed asset,\n address indexed mainOracle,\n address indexed pivotOracle,\n address fallbackOracle\n );\n\n /// Event emitted when an oracle is set\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\n\n /// Event emitted when an oracle is enabled or disabled\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\n\n /**\n * @notice Checks whether an address is null or not\n */\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /**\n * @notice Checks whether token config exists by checking whether asset is null address\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\n * @param asset asset address\n */\n modifier checkTokenConfigExistence(address asset) {\n if (tokenConfigs[asset].asset == address(0)) revert(\"token config must exist\");\n _;\n }\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\n /// (e.g vETH on ethereum would not be supported, only vWETH)\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\n /// Set to address(0) of VAI is not existent.\n /// @param _boundValidator Address of the bound validator contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address nativeMarketAddress,\n address vaiAddress,\n BoundValidatorInterface _boundValidator\n ) notNullAddress(address(_boundValidator)) {\n nativeMarket = nativeMarketAddress;\n vai = vaiAddress;\n boundValidator = _boundValidator;\n\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract admin and sets the BoundValidator contract address\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n }\n\n /**\n * @notice Pauses oracle\n * @custom:access Only Governance\n */\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n _pause();\n }\n\n /**\n * @notice Unpauses oracle\n * @custom:access Only Governance\n */\n function unpause() external {\n _checkAccessAllowed(\"unpause()\");\n _unpause();\n }\n\n /**\n * @notice Batch sets token configs\n * @param tokenConfigs_ Token config array\n * @custom:access Only Governance\n * @custom:error Throws a length error if the length of the token configs array is 0\n */\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\n if (tokenConfigs_.length == 0) revert(\"length can't be 0\");\n uint256 numTokenConfigs = tokenConfigs_.length;\n for (uint256 i; i < numTokenConfigs; ) {\n setTokenConfig(tokenConfigs_[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Sets oracle for a given asset and role.\n * @dev Supplied asset **must** exist and main oracle may not be null\n * @param asset Asset address\n * @param oracle Oracle address\n * @param role Oracle role\n * @custom:access Only Governance\n * @custom:error Null address error if main-role oracle address is null\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\n */\n function setOracle(\n address asset,\n address oracle,\n OracleRole role\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"setOracle(address,address,uint8)\");\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\"can't set zero address to main oracle\");\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\n emit OracleSet(asset, oracle, uint256(role));\n }\n\n /**\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\n * @param asset Asset address\n * @param role Oracle role\n * @param enable Enabled boolean of the oracle\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n */\n function enableOracle(\n address asset,\n OracleRole role,\n bool enable\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"enableOracle(address,uint8,bool)\");\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\n emit OracleEnabled(asset, uint256(role), enable);\n }\n\n /**\n * @notice Updates the TWAP pivot oracle price.\n * @dev This function should always be called before calling getUnderlyingPrice\n * @param vToken vToken address\n */\n function updatePrice(address vToken) external override {\n address asset = _getUnderlyingAsset(vToken);\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @notice Updates the pivot oracle price. Currently using TWAP\n * @dev This function should always be called before calling getPrice\n * @param asset asset address\n */\n function updateAssetPrice(address asset) external {\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @dev Gets token config by asset address\n * @param asset asset address\n * @return tokenConfig Config for the asset\n */\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\n return tokenConfigs[asset];\n }\n\n /**\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\n * - Check if the oracle is paused globally\n * - Validate price from main oracle against pivot oracle\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\n * - Validate price from main oracle against fallback oracle if the second validation failed\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\n * main oracle price is returned.\n * @param vToken vToken address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n\n address asset = _getUnderlyingAsset(vToken);\n return _getPrice(asset);\n }\n\n /**\n * @notice Gets price of the asset\n * @param asset asset address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getPrice(address asset) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n return _getPrice(asset);\n }\n\n /**\n * @notice Sets/resets single token configs.\n * @dev main oracle **must not** be a null address\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress is thrown if asset address is null\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(\n tokenConfig.asset,\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\n );\n }\n\n /**\n * @notice Gets oracle and enabled status by asset address\n * @param asset asset address\n * @param role Oracle role\n * @return oracle Oracle address based on role\n * @return enabled Enabled flag of the oracle based on token config\n */\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\n oracle = tokenConfigs[asset].oracles[uint256(role)];\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\n }\n\n function _getPrice(address asset) internal view returns (uint256) {\n uint256 pivotPrice = INVALID_PRICE;\n\n // Get pivot oracle price, Invalid price if not available or error\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracleEnabled && pivotOracle != address(0)) {\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\n pivotPrice = pricePivot;\n } catch {}\n }\n\n // Compare main price and pivot price, return main price and if validation was successful\n // note: In case pivot oracle is not available but main price is available and\n // validation is successful, the main oracle price is returned.\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\n asset,\n pivotPrice,\n pivotOracleEnabled && pivotOracle != address(0)\n );\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\n\n // Compare fallback and pivot if main oracle comparision fails with pivot\n // Return fallback price when fallback price is validated successfully with pivot oracle\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\n\n // Lastly compare main price and fallback price\n if (\n mainPrice != INVALID_PRICE &&\n fallbackPrice != INVALID_PRICE &&\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\n ) {\n return mainPrice;\n }\n\n revert(\"invalid resilient oracle price\");\n }\n\n /**\n * @notice Gets a price for the provided asset\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\n * able to fetch a correct price\n * @param asset asset address\n * @param pivotPrice Pivot oracle price\n * @param pivotEnabled If pivot oracle is not empty and enabled\n * @return price USD price in scaled decimals\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\n * @return pivotValidated Boolean representing if the validation of main oracle price\n * and pivot oracle price were successful\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\n * address is null\n */\n function _getMainOraclePrice(\n address asset,\n uint256 pivotPrice,\n bool pivotEnabled\n ) internal view returns (uint256, bool) {\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\n if (mainOracleEnabled && mainOracle != address(0)) {\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\n if (!pivotEnabled) {\n return (mainOraclePrice, true);\n }\n if (pivotPrice == INVALID_PRICE) {\n return (mainOraclePrice, false);\n }\n return (\n mainOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\n * @param asset asset address\n * @return price USD price in 18 decimals\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\n * and pivot oracle price were successfull\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\n * address is null\n */\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\n if (fallbackEnabled && fallbackOracle != address(0)) {\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\n if (pivotPrice == INVALID_PRICE) {\n return (fallbackOraclePrice, false);\n }\n return (\n fallbackOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function returns the underlying asset of a vToken\n * @param vToken vToken address\n * @return asset underlying asset address\n */\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\n if (vToken == nativeMarket) {\n asset = NATIVE_TOKEN_ADDR;\n } else if (vToken == vai) {\n asset = vai;\n } else {\n asset = VBep20Interface(vToken).underlying();\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\nuint256 constant EXP_SCALE = 1e18;\n\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\nuint256 constant MANTISSA_ONE = EXP_SCALE;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\n" + }, + "@venusprotocol/solidity-utilities/contracts/validators.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\nerror ZeroAddressNotAllowed();\n\n/// @notice Thrown if the supplied value is 0 where it is not allowed\nerror ZeroValueNotAllowed();\n\n/// @notice Checks if the provided address is nonzero, reverts otherwise\n/// @param address_ Address to check\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\nfunction ensureNonzeroAddress(address address_) pure {\n if (address_ == address(0)) {\n revert ZeroAddressNotAllowed();\n }\n}\n\n/// @notice Checks if the provided value is nonzero, reverts otherwise\n/// @param value_ Value to check\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\nfunction ensureNonzeroValue(uint256 value_) pure {\n if (value_ == 0) {\n revert ZeroValueNotAllowed();\n }\n}\n" + }, + "contracts/Interfaces/IComptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IComptroller {\n function isComptroller() external view returns (bool);\n\n function markets(address) external view returns (bool);\n\n function getAllMarkets() external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IConverterNetwork.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAbstractTokenConverter } from \"../TokenConverter/IAbstractTokenConverter.sol\";\n\n/**\n * @title IConverterNetwork\n * @author Venus\n * @notice Interface implemented by `ConverterNetwork`.\n */\ninterface IConverterNetwork {\n /// @notice Adds new converter to the array\n /// @param _tokenConverter Address of the token converter\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Removes converter from the array\n /// @param _tokenConverter Address of the token converter\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice This function returns the array containing all the converters addresses\n /// @return Array containing all the converters addresses\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\n\n /// @notice This function checks for given address is converter or not\n /// @param _tokenConverter Address of the token converter\n /// @return boolean true if given address is converter otherwise false\n function isTokenConverter(address _tokenConverter) external view returns (bool);\n}\n" + }, + "contracts/Interfaces/IPoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IPoolRegistry {\n /// @notice Get VToken in the Pool for an Asset\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\n\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IRiskFund.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IRiskFund\n * @author Venus\n * @notice Interface implemented by `RiskFund`.\n */\ninterface IRiskFund {\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updatePoolState(\n address comptroller,\n address asset,\n uint256 amount\n ) external;\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n\n/**\n * @title IRiskFundGetters\n * @author Venus\n * @notice Interface implemented by `RiskFund` for getter methods.\n */\ninterface IRiskFundGetters {\n function convertibleBaseAsset() external view returns (address);\n}\n" + }, + "contracts/Interfaces/IVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IVToken {\n function underlying() external view returns (address);\n}\n" + }, + "contracts/Test/Mocks/MockConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\n\nimport { AbstractTokenConverter } from \"../../TokenConverter/AbstractTokenConverter.sol\";\nimport { IRiskFundGetters } from \"../../Interfaces/IRiskFund.sol\";\n\ncontract MockConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) public assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) public poolsAssetsReserves;\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n function mockPrivateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 balanceDiff\n ) external {\n _privateConversion(comptroller, tokenAddressOut, balanceDiff);\n }\n\n function AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) public initializer {\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n assetsReserves[tokenAddressIn] += convertedTokenInBalance;\n poolsAssetsReserves[comptroller][tokenAddressIn] += convertedTokenInBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @notice Get base asset address\n function _getDestinationBaseAsset() internal view override returns (address) {\n return IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/Test/Mocks/MockRiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { RiskFundConverter } from \"../../TokenConverter/RiskFundConverter.sol\";\n\ncontract MockRiskFundConverter is RiskFundConverter {\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) RiskFundConverter(corePoolComptroller_, vBNB_, nativeWrapped_) {}\n\n function postConversionHookMock(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) external {\n super._postConversionHook(tokenInAddress, tokenOutAddress, amountIn, amountOut);\n }\n\n function preTransferHookMock(address tokenOutAddress, uint256 amountOut) external {\n super._preTransferHook(tokenOutAddress, amountOut);\n }\n\n function setAssetsReserves(address asset, uint256 amount) external {\n assetsReserves[asset] = amount;\n }\n\n function setPoolsAssetsReserves(\n address comptroller,\n address asset,\n uint256 amount\n ) external {\n poolsAssetsReserves[comptroller][asset] = amount;\n }\n\n function getPoolsAssetsReserves(address comptroller, address asset) external view returns (uint256) {\n return poolsAssetsReserves[comptroller][asset];\n }\n\n function getAssetsReserves(address asset) external view returns (uint256) {\n return assetsReserves[asset];\n }\n}\n" + }, + "contracts/TokenConverter/AbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { MANTISSA_ONE, EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\nimport { IAbstractTokenConverter } from \"./IAbstractTokenConverter.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @title AbstractTokenConverter\n/// @author Venus\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\n/*\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\n *\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\n * a. convertExactTokensSupportingFeeOnTransferTokens\n * b. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\n * similar to Case I.\n *\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * a. convertExactTokens\n * b. convertForExactTokens\n * c. convertExactTokensSupportingFeeOnTransferTokens\n * d. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * similar to Case III.\n *\n * ------------------------------------------------------------------------------------------------------------------------------------\n * Example 1:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInAmount - 100\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\n * function for tokenIn as deflationary token.\n *\n * Example 2:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\n * tokenOutAmount - 70\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\n * ------------------------------------------------------------------------------------------------------------------------------------\n *\n * This contract also supports private conversion between the converters:\n * Private conversions:\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\n *\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\n *\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\n * tokenAddressOut: As base asset of that converter.\n *\n * ConverterNetwork:\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\n * and tokenAddressOut provided.\n *\n * findTokenConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\n *\n * findTokenConvertersForConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\n */\n\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Maximum incentive could be\n uint256 public constant MAX_INCENTIVE = 0.5e18;\n\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\n uint256 public minAmountToConvert;\n\n /// @notice Venus price oracle contract\n ResilientOracle public priceOracle;\n\n /// @notice conversion configurations for the existing pairs\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\n\n /// @notice Address that all incoming tokens are transferred to\n address public destinationAddress;\n\n /// @notice Boolean for if conversion is paused\n bool public conversionPaused;\n\n /// @notice Address of the converterNetwork contract\n IConverterNetwork public converterNetwork;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n uint256[45] private __gap;\n\n /// @notice Emitted when config is updated for tokens pair\n event ConversionConfigUpdated(\n address indexed tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 oldIncentive,\n uint256 newIncentive,\n ConversionAccessibility oldAccess,\n ConversionAccessibility newAccess\n );\n /// @notice Emitted when price oracle address is updated\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\n\n /// @notice Emitted when destination address is updated\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\n\n /// @notice Emitted when converterNetwork address is updated\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\n\n /// @notice Emitted when exact amount of tokens are converted for tokens\n event ConvertedExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens\n event ConvertedForExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when conversion is paused\n event ConversionPaused(address indexed sender);\n\n /// @notice Emitted when conversion is unpaused\n event ConversionResumed(address indexed sender);\n\n /// @notice Event emitted when tokens are swept\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\n error AmountOutMismatched();\n\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\n error AmountInMismatched();\n\n /// @notice Thrown when given input amount is zero\n error InsufficientInputAmount();\n\n /// @notice Thrown when given output amount is zero\n error InsufficientOutputAmount();\n\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\n error ConversionConfigNotEnabled();\n\n /// @notice Thrown when conversion is enabled only for private conversions\n error ConversionEnabledOnlyForPrivateConversions();\n\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n error InvalidToAddress();\n\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\n\n /// @notice Thrown when amountOut is lower than amountOutMin\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\n\n /// @notice Thrown when amountIn is higher than amountInMax\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\n\n /// @notice Thrown when conversion is paused\n error ConversionTokensPaused();\n\n /// @notice Thrown when conversion is Active\n error ConversionTokensActive();\n\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\n error InvalidTokenConfigAddresses();\n\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\n error InsufficientPoolLiquidity();\n\n /// @notice When address of the ConverterNetwork is not set or Zero address\n error InvalidConverterNetwork();\n\n /// @notice Thrown when trying to set non zero incentive for private conversion\n error NonZeroIncentiveForPrivateConversion();\n\n /// @notice Thrown when using convertForExactTokens deflationary tokens\n error DeflationaryTokenNotSupported();\n\n /// @notice Thrown when minimum amount to convert is zero\n error InvalidMinimumAmountToConvert();\n\n /// @notice Thrown when there is a mismatch in the length of input arrays\n error InputLengthMisMatch();\n\n /**\n * @notice Modifier to ensure valid conversion parameters for a token conversion\n * and check if conversion is paused or not\n * @param to The recipient address for the converted tokens\n * @param tokenAddressIn The input token address for the conversion\n * @param tokenAddressOut The output token address for the conversion\n */\n modifier validConversionParameters(\n address to,\n address tokenAddressIn,\n address tokenAddressOut\n ) {\n _checkConversionPaused();\n ensureNonzeroAddress(to);\n if (to == tokenAddressIn || to == tokenAddressOut) {\n revert InvalidToAddress();\n }\n _;\n }\n\n /// @notice Pause conversion of tokens\n /// @custom:event Emits ConversionPaused on success\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\n /// @custom:access Restricted by ACM\n function pauseConversion() external {\n _checkAccessAllowed(\"pauseConversion()\");\n _checkConversionPaused();\n conversionPaused = true;\n emit ConversionPaused(msg.sender);\n }\n\n /// @notice Resume conversion of tokens.\n /// @custom:event Emits ConversionResumed on success\n /// @custom:error ConversionTokensActive thrown when conversion is already active\n /// @custom:access Restricted by ACM\n function resumeConversion() external {\n _checkAccessAllowed(\"resumeConversion()\");\n if (!conversionPaused) {\n revert ConversionTokensActive();\n }\n\n conversionPaused = false;\n emit ConversionResumed(msg.sender);\n }\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:access Only Governance\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\n _setPriceOracle(priceOracle_);\n }\n\n /// @notice Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:access Only Governance\n function setDestination(address destinationAddress_) external onlyOwner {\n _setDestination(destinationAddress_);\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:access Only Governance\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\n _setConverterNetwork(converterNetwork_);\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:access Only Governance\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n _setMinAmountToConvert(minAmountToConvert_);\n }\n\n /// @notice Batch sets the conversion configurations\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressesOut Array of addresses of tokenOut\n /// @param conversionConfigs Array of conversionConfig config details to update\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\n function setConversionConfigs(\n address tokenAddressIn,\n address[] calldata tokenAddressesOut,\n ConversionConfig[] calldata conversionConfigs\n ) external {\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\n\n for (uint256 i; i < tokenOutArrayLength; ) {\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountIn != amountInMantissa) {\n revert AmountInMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\n /// otherwise the amount is adjusted\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountOut != amountOutMantissa) {\n revert AmountOutMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\n /// @param tokenAddress The address of the ERC-20 token to sweep\n /// @param to The address to which tokens will be transferred\n /// @param amount The amount to transfer\n /// @custom:event Emits SweepToken event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\n /// @custom:access Only Governance\n function sweepToken(\n address tokenAddress,\n address to,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(to);\n ensureNonzeroValue(amount);\n\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n preSweepToken(tokenAddress, amount);\n token.safeTransfer(to, amount);\n\n emit SweepToken(tokenAddress, to, amount);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\n /// @dev This function retrieves values without altering token prices\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n amountConvertedMantissa = amountInMantissa;\n uint256 tokenInToOutConversion;\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountConvertedMantissa = _divRoundingUp(maxTokenOutReserve * EXP_SCALE, tokenInToOutConversion);\n amountOutMantissa = maxTokenOutReserve;\n }\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @dev This function retrieves values without altering token prices\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountOutMantissa = maxTokenOutReserve;\n }\n\n amountConvertedMantissa = amountOutMantissa;\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountInMantissa;\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountOutMantissa;\n }\n\n /// @notice This method updated the states of this contract after getting funds from PSR\n /// after settling the amount(if any) through privateConversion between converters\n /// @dev This function is called by protocolShareReserve\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\n if (balanceDiff > 0) {\n _privateConversion(comptroller, asset, balanceDiff);\n }\n }\n\n /// @notice Set the configuration for new or existing conversion pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n /// @custom:event Emits ConversionConfigUpdated event on success\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\n /// @custom:access Controlled by AccessControlManager\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) public {\n _checkAccessAllowed(\"setConversionConfig(address,address,ConversionConfig)\");\n ensureNonzeroAddress(tokenAddressIn);\n ensureNonzeroAddress(tokenAddressOut);\n\n if (conversionConfig.incentive > MAX_INCENTIVE) {\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\n }\n\n if (\n (tokenAddressIn == tokenAddressOut) ||\n (tokenAddressIn != _getDestinationBaseAsset()) ||\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\n ) {\n revert InvalidTokenConfigAddresses();\n }\n\n if (\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\n conversionConfig.incentive != 0\n ) {\n revert NonZeroIncentiveForPrivateConversion();\n }\n\n if (\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\n (address(converterNetwork) == address(0))\n ) {\n revert InvalidConverterNetwork();\n }\n\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n emit ConversionConfigUpdated(\n tokenAddressIn,\n tokenAddressOut,\n configuration.incentive,\n conversionConfig.incentive,\n configuration.conversionAccess,\n conversionConfig.conversionAccess\n );\n\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\n } else {\n configuration.incentive = conversionConfig.incentive;\n configuration.conversionAccess = conversionConfig.conversionAccess;\n }\n }\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\n\n /// @dev Operations to perform before sweeping tokens\n /// @param token Address of the token\n /// @param amount Amount transferred to address(to)\n function preSweepToken(address token, uint256 amount) internal virtual {}\n\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function _convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n if (amountOutMantissa < amountOutMinMantissa) {\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n }\n\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\n /// it is called by convertForExactTokens function\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n if (actualAmountIn != amountInMantissa) {\n revert DeflationaryTokenNotSupported();\n }\n\n if (actualAmountIn > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n actualAmountOut = amountOutMantissa;\n }\n\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n if (amountInMantissa > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\n }\n\n /// @dev return actualAmountOut from reserves for tokenAddressOut\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\n function _doTransferOut(\n address tokenAddressOut,\n address to,\n uint256 amountConvertedMantissa\n ) internal {\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountConvertedMantissa) {\n revert InsufficientPoolLiquidity();\n }\n\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\n\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\n tokenOut.safeTransfer(to, amountConvertedMantissa);\n }\n\n /// @notice Transfer tokenAddressIn from user to destination\n /// @param tokenAddressIn Address of the token to convert\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @return actualAmountIn Actual amount transferred to destination\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\n }\n\n /// @dev Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:event Emits PriceOracleUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\n ensureNonzeroAddress(address(priceOracle_));\n emit PriceOracleUpdated(priceOracle, priceOracle_);\n priceOracle = priceOracle_;\n }\n\n /// @dev Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:event Emits DestinationAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\n function _setDestination(address destinationAddress_) internal {\n ensureNonzeroAddress(destinationAddress_);\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\n destinationAddress = destinationAddress_;\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\n ensureNonzeroAddress(address(converterNetwork_));\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\n converterNetwork = converterNetwork_;\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:event MinAmountToConvertUpdated is emitted in success\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\n ensureNonzeroValue(minAmountToConvert_);\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\n minAmountToConvert = minAmountToConvert_;\n }\n\n /// @dev Hook to perform after converting tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param amountIn Amount of tokenIn converted\n /// @param amountOut Amount of tokenOut converted\n function _postConversionHook(\n address tokenAddressIn,\n address tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n ) internal virtual {}\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init_unchained(\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n _setPriceOracle(priceOracle_);\n _setDestination(destinationAddress_);\n _setMinAmountToConvert(minAmountToConvert_);\n conversionPaused = false;\n }\n\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return Amount of asset, for _privateConversion\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\n\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\n /// destination contract as destination's base asset\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\n function _privateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 amountToConvert\n ) internal {\n address tokenAddressIn = _getDestinationBaseAsset();\n address _destinationAddress = destinationAddress;\n uint256 convertedTokenInBalance;\n if (address(converterNetwork) != address(0)) {\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\n uint256 convertersLength = converterAddresses.length;\n for (uint256 i; i < convertersLength; ) {\n if (converterBalances[i] == 0) break;\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\n converterBalances[i],\n tokenAddressOut,\n tokenAddressIn\n );\n if (amountIn > amountToConvert) {\n amountIn = amountToConvert;\n }\n\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\n break;\n }\n\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\n amountIn,\n 0,\n tokenAddressOut,\n tokenAddressIn,\n _destinationAddress\n );\n\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n amountToConvert -= amountIn;\n convertedTokenInBalance += (balanceAfter - balanceBefore);\n\n if (amountToConvert == 0) break;\n unchecked {\n ++i;\n }\n }\n }\n\n _postPrivateConversionHook(\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance,\n tokenAddressOut,\n amountToConvert\n );\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal virtual {}\n\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\n\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\n /// @param amountIn The amount to convert\n /// @param tokenAddress Address of the token\n /// @return isValid true if amount to convert is greater than minimum amount to convert\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\n priceOracle.updateAssetPrice(tokenAddress);\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\n\n if (amountInInUsd >= minAmountToConvert) {\n isValid = true;\n }\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\n if (amountInMantissa == 0) {\n revert InsufficientInputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\n /// multiplied by conversionWithIncentive which will be >= 1\n amountOutMantissa = (amountInMantissa * tokenInToOutConversion) / (EXP_SCALE);\n }\n\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\n if (amountOutMantissa == 0) {\n revert InsufficientOutputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\n converterNetwork.isTokenConverter(msg.sender);\n if (isPrivateConversion) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\n if (isPrivateConversion) {\n amountInMantissa =\n (amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) /\n (tokenInUnderlyingPrice * conversionWithIncentive);\n } else {\n amountInMantissa = _divRoundingUp(\n amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE,\n tokenInUnderlyingPrice * conversionWithIncentive\n );\n }\n\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n }\n\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\n if (\n (!(isConverter) &&\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n }\n\n /// @dev To check, is conversion paused\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\n function _checkConversionPaused() internal view {\n if (conversionPaused) {\n revert ConversionTokensPaused();\n }\n }\n\n /// @dev Get base asset address of the destination contract\n /// @return Address of the base asset\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\n\n /// @dev Performs division where the result is rounded up\n /// @param numerator The numerator of the division operation\n /// @param denominator The denominator of the division operation. Must be non-zero\n /// @return The result of the division, rounded up\n function _divRoundingUp(uint256 numerator, uint256 denominator) internal pure returns (uint256) {\n return (numerator + denominator - 1) / denominator;\n }\n}\n" + }, + "contracts/TokenConverter/IAbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @notice Interface for AbstractTokenConverter\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ninterface IAbstractTokenConverter {\n /// @notice This enum define the all possible ways of conversion can happen\n enum ConversionAccessibility {\n NONE, // Conversion is disable for the pair\n ALL, // Conversion is enable for private conversion and users\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\n ONLY_FOR_USERS // Conversion is enable only for users\n }\n\n /// @notice This struct represents the configuration for a token conversion.\n struct ConversionConfig {\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\n uint256 incentive;\n /// enable or disable conversion for users or converters or both or none\n ConversionAccessibility conversionAccess;\n }\n\n /// @notice Pause conversion of tokens\n function pauseConversion() external;\n\n /// @notice Resume conversion of tokens.\n function resumeConversion() external;\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n function setPriceOracle(ResilientOracle priceOracle_) external;\n\n /// @notice Set the configuration for new or existing convert pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) external;\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Get the configuration for the pair of the tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\n /// @return conversionAccess Accessibility for the pair of tokens\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\n external\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\n\n /// @notice Get the address of the converterNetwork\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) external view returns (uint256 tokenBalance);\n}\n" + }, + "contracts/TokenConverter/RiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\nimport { IPoolRegistry } from \"../Interfaces/IPoolRegistry.sol\";\nimport { IComptroller } from \"../Interfaces/IComptroller.sol\";\nimport { IRiskFund, IRiskFundGetters } from \"../Interfaces/IRiskFund.sol\";\nimport { IVToken } from \"../Interfaces/IVToken.sol\";\n\n/// @title RiskFundConverter\n/// @author Venus\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the core pool comptroller\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n ///@notice Address of the vBNB\n ///@dev This address is used to include the BNB market while in getPools method\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable VBNB;\n\n ///@notice Address of the native wrapped currency\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_WRAPPED;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) internal assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\n\n /// @notice Address of pool registry contract\n address public poolRegistry;\n\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\n\n // Error thrown when comptrollers array length is not equal to assets array length\n error InvalidArguments();\n\n /// @notice thrown when amount entered is greater than balance\n error InsufficientBalance();\n\n /// @notice thrown when asset does not exist in the pool\n error MarketNotExistInPool(address comptroller, address asset);\n\n /// @notice thrown to prevent reentrancy\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\n /// cannot be called recursively within the same transaction.\n error ReentrancyGuardError();\n\n /// @param corePoolComptroller_ Address of the Comptroller pool\n /// @param vBNB_ Address of the vBNB\n /// @param nativeWrapped_ Address of the wrapped native currency\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) {\n ensureNonzeroAddress(corePoolComptroller_);\n ensureNonzeroAddress(vBNB_);\n ensureNonzeroAddress(nativeWrapped_);\n\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\n VBNB = vBNB_;\n NATIVE_WRAPPED = nativeWrapped_;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param poolRegistry_ Address of the pool registry\n /// @param minAmountToConvert_ minimum amount to convert\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address poolRegistry_,\n uint256 minAmountToConvert_,\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) public initializer {\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n ensureNonzeroAddress(poolRegistry_);\n poolRegistry = poolRegistry_;\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Pool registry setter\n /// @param poolRegistry_ Address of the pool registry\n /// @custom:event PoolRegistryUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:access Only Governance\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\n poolRegistry = poolRegistry_;\n }\n\n /// @notice Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:access Restricted by ACM\n function setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) external {\n _checkAccessAllowed(\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\");\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return reserves Asset's reserve in risk fund\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n reserves = poolsAssetsReserves[comptroller][asset];\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Reserves of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n tokenBalance = assetsReserves[tokenAddress];\n }\n\n /// @notice Get the array of all pools addresses\n /// @param tokenAddress Address of the token\n /// @return poolsWithCore Array of the pools addresses in which token is available\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\n\n if (isAssetListedInCore(tokenAddress)) {\n uint256 poolsLength = poolsWithCore.length;\n address[] memory extendedPools = new address[](poolsLength + 1);\n\n for (uint256 i; i < poolsLength; ) {\n extendedPools[i] = poolsWithCore[i];\n unchecked {\n ++i;\n }\n }\n\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\n poolsWithCore = extendedPools;\n }\n }\n\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\n assetsReserves[tokenOutAddress] -= amountOut;\n }\n\n /// @notice Hook to perform after converting tokens\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\n /// @param tokenInAddress Address of the tokenIn\n /// @param tokenOutAddress Address of the tokenOut\n /// @param amountIn Amount of tokenIn transferred\n /// @param amountOut Amount of tokenOut transferred\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\n function _postConversionHook(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) internal override {\n address[] memory pools = getPools(tokenOutAddress);\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\n ensureNonzeroValue(assetReserve);\n\n uint256 poolsLength = pools.length;\n uint256 distributedOutShare;\n uint256 poolAmountInShare;\n uint256 distributedInShare;\n\n for (uint256 i; i < poolsLength; ) {\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\n if (currentPoolsAssetsReserves != 0) {\n if (i < (poolsLength - 1)) {\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\n distributedInShare += poolAmountInShare;\n } else {\n uint256 distributedDiff = amountOut - distributedOutShare;\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\n poolAmountInShare = amountIn - distributedInShare;\n }\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\n }\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Operations to perform before sweeping tokens\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\n if (amount > balance) revert InsufficientBalance();\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\n\n if (balanceDiff < amount) {\n uint256 amountDiff;\n unchecked {\n amountDiff = amount - balanceDiff;\n }\n\n address[] memory pools = getPools(tokenAddress);\n uint256 assetReserve = assetsReserves[tokenAddress];\n uint256 poolsLength = pools.length;\n uint256 distributedShare;\n\n for (uint256 i; i < poolsLength; ) {\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\n if (i < (poolsLength - 1)) {\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\n } else {\n uint256 distributedDiff = amountDiff - distributedShare;\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\n }\n }\n unchecked {\n ++i;\n }\n }\n assetsReserves[tokenAddress] -= amountDiff;\n }\n }\n\n /// @dev Update the poolAssetsReserves upon transferring the tokens\n /// @param pool Address of the pool\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @param assetReserve Asset's reserve for the pool\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\n /// @custom:event AssetsReservesUpdated emits on success\n function updatePoolAssetsReserve(\n address pool,\n address tokenAddress,\n uint256 amount,\n uint256 assetReserve\n ) internal returns (uint256 poolAmountShare) {\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\n }\n\n /// @dev Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\n function _setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) internal {\n uint256 comptrollersLength = comptrollers.length;\n\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < comptrollersLength; ) {\n address[] memory poolAssets = assets[i];\n bool[] memory assetsValues = values[i];\n uint256 poolAssetsLength = poolAssets.length;\n\n if (poolAssetsLength != assetsValues.length) {\n revert InvalidArguments();\n }\n\n for (uint256 j; j < poolAssetsLength; ) {\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\n unchecked {\n ++j;\n }\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\n /// and transferring funds to the protocol share reserve\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return balanceDifference Amount of asset, for _privateConversion\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n function _updateAssetsState(address comptroller, address asset)\n internal\n override\n returns (uint256 balanceDifference)\n {\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 currentBalance = token.balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\n token.safeTransfer(destinationAddress, balanceDifference);\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\n\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\n IRiskFund(destinationAddress).updatePoolState(\n comptroller,\n asset,\n newDestinationBalance - previousDestinationBalance\n );\n balanceDifference = 0;\n }\n }\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n emit AssetTransferredToDestination(\n destinationAddress,\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance\n );\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @dev This function checks for the given asset is listed in core pool or not\n /// @param tokenAddress Address of the asset\n /// @return isAssetListed true if the asset is listed\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\n\n uint256 coreMarketsLength = coreMarkets.length;\n for (uint256 i; i < coreMarketsLength; ) {\n isAssetListed = (VBNB == coreMarkets[i])\n ? (tokenAddress == NATIVE_WRAPPED)\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\n\n if (isAssetListed) {\n break;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev This function checks for the given asset is listed or not\n /// @param comptroller Address of the comptroller\n /// @param asset Address of the asset\n /// @return isListed true if the asset is listed\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\n if (comptroller == CORE_POOL_COMPTROLLER) {\n isListed = isAssetListedInCore(asset);\n } else {\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\n }\n }\n\n /// @dev Get base asset address of the RiskFund\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/TokenConverter/SingleTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\n\n/// @title SingleTokenConverter\n/// @author Venus\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract SingleTokenConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the base asset token\n address public baseAsset;\n\n /// @notice Emitted when base asset is updated\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param baseAsset_ Address of the base asset\n /// @param minAmountToConvert_ Minimum amount to convert\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address baseAsset_,\n uint256 minAmountToConvert_\n ) public initializer {\n _setBaseAsset(baseAsset_);\n\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @notice Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:access Only Governance\n function setBaseAsset(address baseAsset_) external onlyOwner {\n _setBaseAsset(baseAsset_);\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address.\n /// @return balanceLeft Amount of asset, for _privateConversion\n // solhint-disable-next-line\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 balance = token.balanceOf(address(this));\n balanceLeft = balance;\n\n if (asset == baseAsset) {\n balanceLeft = 0;\n token.safeTransfer(destinationAddress, balance);\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\n }\n }\n\n /// @dev Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n /// @custom:event BaseAssetUpdated is emitted on success\n function _setBaseAsset(address baseAsset_) internal {\n ensureNonzeroAddress(baseAsset_);\n emit BaseAssetUpdated(baseAsset, baseAsset_);\n baseAsset = baseAsset_;\n }\n\n /// @dev Get base asset address\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = baseAsset;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} From dced648d3085d324b5f27012a1de4f3cfc9630c2 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 28 Feb 2024 08:18:52 +0000 Subject: [PATCH 34/53] feat: updating deployment files --- deployments/bsctestnet.json | 4 ++-- deployments/bsctestnet_addresses.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/deployments/bsctestnet.json b/deployments/bsctestnet.json index 0049df39..5ad37e99 100644 --- a/deployments/bsctestnet.json +++ b/deployments/bsctestnet.json @@ -5127,7 +5127,7 @@ ] }, "RiskFundConverter_Implementation": { - "address": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", + "address": "0x857ebb8CAcb97DE5ab719320c9FB3aa16076bFe3", "abi": [ { "inputs": [ @@ -7584,7 +7584,7 @@ ] }, "SingleTokenConverterImp": { - "address": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", + "address": "0x42Ec3Eb6F23460dFDfa3aE5688f3415CDfE0C6AD", "abi": [ { "inputs": [], diff --git a/deployments/bsctestnet_addresses.json b/deployments/bsctestnet_addresses.json index 7bdc6363..478e5700 100644 --- a/deployments/bsctestnet_addresses.json +++ b/deployments/bsctestnet_addresses.json @@ -12,11 +12,11 @@ "ProtocolShareReserve_Implementation": "0x91B67df8B13a1B53a3828EAAD3f4233B55FEc26d", "ProtocolShareReserve_Proxy": "0x25c7c7D6Bf710949fD7f03364E9BA19a1b3c10E3", "RiskFundConverter": "0x32Fbf7bBbd79355B86741E3181ef8c1D9bD309Bb", - "RiskFundConverter_Implementation": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", + "RiskFundConverter_Implementation": "0x857ebb8CAcb97DE5ab719320c9FB3aa16076bFe3", "RiskFundConverter_Proxy": "0x32Fbf7bBbd79355B86741E3181ef8c1D9bD309Bb", "RiskFundV2": "0xcA2A023FBe3be30b7187E88D7FDE1A9a4358B509", "SingleTokenConverterBeacon": "0xD2410D8B581D37c5B474CD9Ee0C15F02138AC028", - "SingleTokenConverterImp": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", + "SingleTokenConverterImp": "0x42Ec3Eb6F23460dFDfa3aE5688f3415CDfE0C6AD", "USDCPrimeConverter": "0x2ecEdE6989d8646c992344fF6C97c72a3f811A13", "USDTPrimeConverter": "0xf1FA230D25fC5D6CAfe87C5A6F9e1B17Bc6F194E", "XVSVaultConverter": "0x258f49254C758a0E37DAb148ADDAEA851F4b02a2", From 8dc80e99923419147b85021a19733820e16e5ddb Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 28 Feb 2024 19:24:05 +0530 Subject: [PATCH 35/53] feat: update converters deployment files for bscmainnet --- .../RiskFundConverter_Implementation.json | 72 +++++----- .../bscmainnet/SingleTokenConverterImp.json | 67 +++++----- .../91b55240df7761b1edcdbbc6fc102117.json | 123 ++++++++++++++++++ 3 files changed, 193 insertions(+), 69 deletions(-) create mode 100644 deployments/bscmainnet/solcInputs/91b55240df7761b1edcdbbc6fc102117.json diff --git a/deployments/bscmainnet/RiskFundConverter_Implementation.json b/deployments/bscmainnet/RiskFundConverter_Implementation.json index e9c5f066..d6c9cfd5 100644 --- a/deployments/bscmainnet/RiskFundConverter_Implementation.json +++ b/deployments/bscmainnet/RiskFundConverter_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0x2fB02b3D49D45967DA471C7685Ce524d833520Dc", + "address": "0xd420Bf9C31F6b4a98875B6e561b13aCB19210647", "abi": [ { "inputs": [ @@ -1622,30 +1622,30 @@ "type": "function" } ], - "transactionHash": "0x46d6cae2f9bd814a433301172e86111d7e0c3722cdb92780646bf8a87ca07e7e", + "transactionHash": "0x78ca579f97531a8615ab855ace500b7bf2d6f5c744a702afbf37d7aae232e147", "receipt": { "to": null, "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0x2fB02b3D49D45967DA471C7685Ce524d833520Dc", - "transactionIndex": 53, - "gasUsed": "4938849", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000080000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7b3d9f88b694b07156d76a88541c99e9de1339199d8e3bcc0a6e888b4ea0977f", - "transactionHash": "0x46d6cae2f9bd814a433301172e86111d7e0c3722cdb92780646bf8a87ca07e7e", + "contractAddress": "0xd420Bf9C31F6b4a98875B6e561b13aCB19210647", + "transactionIndex": 95, + "gasUsed": "4953922", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000080000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x4047118d5de75f3990f0a1d0253d74c014263bff36d0ee0c34b2bec6e6c87c9e", + "transactionHash": "0x78ca579f97531a8615ab855ace500b7bf2d6f5c744a702afbf37d7aae232e147", "logs": [ { - "transactionIndex": 53, - "blockNumber": 35139909, - "transactionHash": "0x46d6cae2f9bd814a433301172e86111d7e0c3722cdb92780646bf8a87ca07e7e", - "address": "0x2fB02b3D49D45967DA471C7685Ce524d833520Dc", + "transactionIndex": 95, + "blockNumber": 36531527, + "transactionHash": "0x78ca579f97531a8615ab855ace500b7bf2d6f5c744a702afbf37d7aae232e147", + "address": "0xd420Bf9C31F6b4a98875B6e561b13aCB19210647", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "logIndex": 107, - "blockHash": "0x7b3d9f88b694b07156d76a88541c99e9de1339199d8e3bcc0a6e888b4ea0977f" + "logIndex": 248, + "blockHash": "0x4047118d5de75f3990f0a1d0253d74c014263bff36d0ee0c34b2bec6e6c87c9e" } ], - "blockNumber": 35139909, - "cumulativeGasUsed": "9683822", + "blockNumber": 36531527, + "cumulativeGasUsed": "17813249", "status": 1, "byzantium": true }, @@ -1654,11 +1654,11 @@ "0xA07c5b74C9B40447a954e1466938b865b6BBea36", "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c" ], - "numDeployments": 1, - "solcInputHash": "d02e743d886d63634298edb2c3d7a019", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vBNB_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidArguments\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"MarketNotExistInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetsReservesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"name\":\"PoolAssetsDirectTransferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPoolRegistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPoolRegistry\",\"type\":\"address\"}],\"name\":\"PoolRegistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_COMPTROLLER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NATIVE_WRAPPED\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VBNB\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolAssetReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"getPools\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"poolsWithCore\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolsAssetsDirectTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"setPoolsAssetsDirectTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"errors\":{\"ReentrancyGuardError()\":[{\"details\":\"This error is used to safeguard against reentrancy attacks, ensuring that a certain operation cannot be called recursively within the same transaction.\"}]},\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Reserves of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"corePoolComptroller_\":\"Address of the Comptroller pool\",\"nativeWrapped_\":\"Address of the wrapped native currency\",\"vBNB_\":\"Address of the vBNB\"}},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getPoolAssetReserve(address,address)\":{\"custom:error\":\"MarketNotExistInPool When asset does not exist in the pool(comptroller)ReentrancyGuardError thrown to prevent reentrancy during the function execution\",\"details\":\"Get the Amount of the asset in the risk fund for the specific pool\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"},\"returns\":{\"reserves\":\"Asset's reserve in risk fund\"}},\"getPools(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"poolsWithCore\":\"Array of the pools addresses in which token is available\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256,address[],address[][],bool[][])\":{\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"minimum amount to convert\",\"poolRegistry_\":\"Address of the pool registry\",\"priceOracle_\":\"Resilient oracle address\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPoolRegistry(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"custom:event\":\"PoolRegistryUpdated emits on success\",\"details\":\"Pool registry setter\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"custom:access\":\"Restricted by ACM\",\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"stateVariables\":{\"CORE_POOL_COMPTROLLER\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"NATIVE_WRAPPED\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"VBNB\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\",\"details\":\"This address is used to include the BNB market while in getPools method\"},\"poolsAssetsDirectTransfer\":{\"details\":\"Comptroller(pool) -> Asset -> bool(should transfer directly on true)\"},\"poolsAssetsReserves\":{\"details\":\"Comptroller(pool) -> Asset -> amount\"}},\"title\":\"RiskFundConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"MarketNotExistInPool(address,address)\":[{\"notice\":\"thrown when asset does not exist in the pool\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"ReentrancyGuardError()\":[{\"notice\":\"thrown to prevent reentrancy\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Emitted after updating of the assets reserves amount -> reserve increased by amount\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDirectTransferUpdated(address,address,bool)\":{\"notice\":\"Emitted after the poolsAssetsDirectTransfer mapping is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_COMPTROLLER()\":{\"notice\":\"Address of the core pool comptroller\"},\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"NATIVE_WRAPPED()\":{\"notice\":\"Address of the native wrapped currency\"},\"VBNB()\":{\"notice\":\"Address of the vBNB\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getPools(address)\":{\"notice\":\"Get the array of all pools addresses\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"poolRegistry()\":{\"notice\":\"Address of pool registry contract\"},\"poolsAssetsDirectTransfer(address,address)\":{\"notice\":\"The mapping contains the assets for each pool which are sent to RiskFund directly\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"notice\":\"Update the poolsAssetsDirectTransfer mapping\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"RiskFundConverter used for token conversions and sends received token to RiskFund\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/RiskFundConverter.sol\":\"RiskFundConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IComptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IComptroller {\\n function isComptroller() external view returns (bool);\\n\\n function markets(address) external view returns (bool);\\n\\n function getAllMarkets() external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x7d85db8d34103352b25f29f591c1e45159222f0d2bbafaa3fcd42f42bf9a523d\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IPoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IPoolRegistry {\\n /// @notice Get VToken in the Pool for an Asset\\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\\n\\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb38a3b61926e55588096e0657b758b178130386143a5658030d659038ec7075c\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IVToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IVToken {\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x0718e50835da441b2dddcf6d52a671c43d386b96dbcc9eb41d68c3647b82c117\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa =\\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\\n tokenInToOutConversion; //round-up\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa =\\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\\n (tokenOutUnderlyingPrice * EXP_SCALE);\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n}\\n\",\"keccak256\":\"0xe10a4505a941511a1e57e162dc5b7d6e4874e40ad421828bc4d6366b51b5608c\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/RiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\nimport { IPoolRegistry } from \\\"../Interfaces/IPoolRegistry.sol\\\";\\nimport { IComptroller } from \\\"../Interfaces/IComptroller.sol\\\";\\nimport { IRiskFund, IRiskFundGetters } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IVToken } from \\\"../Interfaces/IVToken.sol\\\";\\n\\n/// @title RiskFundConverter\\n/// @author Venus\\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the core pool comptroller\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable CORE_POOL_COMPTROLLER;\\n\\n ///@notice Address of the vBNB\\n ///@dev This address is used to include the BNB market while in getPools method\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable VBNB;\\n\\n ///@notice Address of the native wrapped currency\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable NATIVE_WRAPPED;\\n\\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\\n mapping(address => uint256) internal assetsReserves;\\n\\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\\n /// @dev Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\\n\\n /// @notice Address of pool registry contract\\n address public poolRegistry;\\n\\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\\n\\n /// @notice Emitted when pool registry address is updated\\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\\n\\n /// @notice Emitted after updating of the assets reserves\\n /// amount -> reserve increased by amount\\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\\n\\n // Error thrown when comptrollers array length is not equal to assets array length\\n error InvalidArguments();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice thrown when asset does not exist in the pool\\n error MarketNotExistInPool(address comptroller, address asset);\\n\\n /// @notice thrown to prevent reentrancy\\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\\n /// cannot be called recursively within the same transaction.\\n error ReentrancyGuardError();\\n\\n /// @param corePoolComptroller_ Address of the Comptroller pool\\n /// @param vBNB_ Address of the vBNB\\n /// @param nativeWrapped_ Address of the wrapped native currency\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address corePoolComptroller_,\\n address vBNB_,\\n address nativeWrapped_\\n ) {\\n ensureNonzeroAddress(corePoolComptroller_);\\n ensureNonzeroAddress(vBNB_);\\n ensureNonzeroAddress(nativeWrapped_);\\n\\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\\n VBNB = vBNB_;\\n NATIVE_WRAPPED = nativeWrapped_;\\n\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param poolRegistry_ Address of the pool registry\\n /// @param minAmountToConvert_ minimum amount to convert\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address poolRegistry_,\\n uint256 minAmountToConvert_,\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) public initializer {\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n ensureNonzeroAddress(poolRegistry_);\\n poolRegistry = poolRegistry_;\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Pool registry setter\\n /// @param poolRegistry_ Address of the pool registry\\n /// @custom:event PoolRegistryUpdated emits on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:access Only Governance\\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\\n ensureNonzeroAddress(poolRegistry_);\\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\\n poolRegistry = poolRegistry_;\\n }\\n\\n /// @notice Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:access Restricted by ACM\\n function setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) external {\\n _checkAccessAllowed(\\\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\\\");\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return reserves Asset's reserve in risk fund\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n reserves = poolsAssetsReserves[comptroller][asset];\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Reserves of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n tokenBalance = assetsReserves[tokenAddress];\\n }\\n\\n /// @notice Get the array of all pools addresses\\n /// @param tokenAddress Address of the token\\n /// @return poolsWithCore Array of the pools addresses in which token is available\\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\\n\\n if (isAssetListedInCore(tokenAddress)) {\\n uint256 poolsLength = poolsWithCore.length;\\n address[] memory extendedPools = new address[](poolsLength + 1);\\n\\n for (uint256 i; i < poolsLength; ) {\\n extendedPools[i] = poolsWithCore[i];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\\n poolsWithCore = extendedPools;\\n }\\n }\\n\\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\\n assetsReserves[tokenOutAddress] -= amountOut;\\n }\\n\\n /// @notice Hook to perform after converting tokens\\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\\n /// @param tokenInAddress Address of the tokenIn\\n /// @param tokenOutAddress Address of the tokenOut\\n /// @param amountIn Amount of tokenIn transferred\\n /// @param amountOut Amount of tokenOut transferred\\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\\n function _postConversionHook(\\n address tokenInAddress,\\n address tokenOutAddress,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal override {\\n address[] memory pools = getPools(tokenOutAddress);\\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\\n ensureNonzeroValue(assetReserve);\\n\\n uint256 poolsLength = pools.length;\\n uint256 distributedOutShare;\\n uint256 poolAmountInShare;\\n uint256 distributedInShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\\n if (currentPoolsAssetsReserves != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\\n distributedInShare += poolAmountInShare;\\n } else {\\n uint256 distributedDiff = amountOut - distributedOutShare;\\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\\n poolAmountInShare = amountIn - distributedInShare;\\n }\\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n\\n address[] memory pools = getPools(tokenAddress);\\n uint256 assetReserve = assetsReserves[tokenAddress];\\n uint256 poolsLength = pools.length;\\n uint256 distributedShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\\n } else {\\n uint256 distributedDiff = amountDiff - distributedShare;\\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n assetsReserves[tokenAddress] -= amountDiff;\\n }\\n }\\n\\n /// @dev Update the poolAssetsReserves upon transferring the tokens\\n /// @param pool Address of the pool\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @param assetReserve Asset's reserve for the pool\\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\\n /// @custom:event AssetsReservesUpdated emits on success\\n function updatePoolAssetsReserve(\\n address pool,\\n address tokenAddress,\\n uint256 amount,\\n uint256 assetReserve\\n ) internal returns (uint256 poolAmountShare) {\\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\\n }\\n\\n /// @dev Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\\n function _setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) internal {\\n uint256 comptrollersLength = comptrollers.length;\\n\\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 i; i < comptrollersLength; ) {\\n address[] memory poolAssets = assets[i];\\n bool[] memory assetsValues = values[i];\\n uint256 poolAssetsLength = poolAssets.length;\\n\\n if (poolAssetsLength != assetsValues.length) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 j; j < poolAssetsLength; ) {\\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\\n unchecked {\\n ++j;\\n }\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// and transferring funds to the protocol share reserve\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return balanceDifference Amount of asset, for _privateConversion\\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n function _updateAssetsState(address comptroller, address asset)\\n internal\\n override\\n returns (uint256 balanceDifference)\\n {\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 currentBalance = token.balanceOf(address(this));\\n uint256 assetReserve = assetsReserves[asset];\\n if (currentBalance > assetReserve) {\\n unchecked {\\n balanceDifference = currentBalance - assetReserve;\\n }\\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\\n token.safeTransfer(destinationAddress, balanceDifference);\\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\\n\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\\n IRiskFund(destinationAddress).updatePoolState(\\n comptroller,\\n asset,\\n newDestinationBalance - previousDestinationBalance\\n );\\n balanceDifference = 0;\\n }\\n }\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal override {\\n if (convertedTokenInBalance > 0) {\\n emit AssetTransferredToDestination(\\n destinationAddress,\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance\\n );\\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\\n }\\n if (convertedTokenOutBalance > 0) {\\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed in core pool or not\\n /// @param tokenAddress Address of the asset\\n /// @return isAssetListed true if the asset is listed\\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\\n\\n uint256 coreMarketsLength = coreMarkets.length;\\n for (uint256 i; i < coreMarketsLength; ) {\\n isAssetListed = (VBNB == coreMarkets[i])\\n ? (tokenAddress == NATIVE_WRAPPED)\\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\\n\\n if (isAssetListed) {\\n break;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed or not\\n /// @param comptroller Address of the comptroller\\n /// @param asset Address of the asset\\n /// @return isListed true if the asset is listed\\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\\n if (comptroller == CORE_POOL_COMPTROLLER) {\\n isListed = isAssetListedInCore(asset);\\n } else {\\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n }\\n\\n /// @dev Get base asset address of the RiskFund\\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\\n }\\n}\\n\",\"keccak256\":\"0xa9fda55440f25049f1946980b801723cf2111584253a1c11ac1bb7d773cbe39e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b5060405162005a8738038062005a8783398101604081905262000034916200018a565b6200003f8362000081565b6200004a8262000081565b620000558162000081565b6001600160a01b0380841660805282811660a052811660c05262000078620000ac565b505050620001d4565b6001600160a01b038116620000a9576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff1615620001195760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016b576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018557600080fd5b919050565b600080600060608486031215620001a057600080fd5b620001ab846200016d565b9250620001bb602085016200016d565b9150620001cb604085016200016d565b90509250925092565b60805160a05160c05161586062000227600039600081816103e20152612d080152600081816103bb0152612c450152600081816106c501528181610d7a01528181612b8c015261346501526158606000f3fe608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614db1565b6106f0565b005b61037b610376366004614dce565b610704565b60408051928352602083019190915201610315565b61036661039e366004614db1565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e10565b6107d0565b610343610425366004614e6f565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614db1565b61091a565b610366610467366004614db1565b61092b565b61036661047a366004614ef4565b61093c565b61036661048d366004614f8e565b610973565b610366610b4a565b6104ad6104a8366004614db1565b610c30565b604051610315919061507b565b61037b6104c8366004614dce565b610dcc565b6103666104db3660046150c8565b610eca565b61037b6104ee366004614dce565b610f71565b61037b610501366004614dce565b61107a565b610519610514366004614e6f565b611179565b604051908152602001610315565b610519610535366004614db1565b6001600160a01b0316600090815261012d602052604090205490565b61036661123e565b610366610567366004615109565b611252565b610366611299565b610366610582366004614db1565b611324565b6033546001600160a01b0316610301565b61037b6105a6366004614e10565b6113ab565b6103666105b9366004614e6f565b6114a1565b61012f54610301906001600160a01b031681565b6106076105e0366004614e6f565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b60405161031592919061518c565b6097546001600160a01b0316610301565b61037b610634366004614e10565b6114d7565b6103666115cd565b61036661064f3660046151a0565b61167f565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e10565b61171d565b6103666106a8366004615250565b61184c565b6103666106bb366004614db1565b611bf5565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c7e565b61070181611cd8565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615122565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d55565b508092505050935093915050565b6107c7611c7e565b61070181612079565b6000808285856107de61216e565b6107e7836121c3565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610857612203565b6108648a8a8a8a8a61225c565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c7e565b61070181612657565b610933611c7e565b610701816126d4565b61095d6040518060600160405280603c81526020016157ef603c9139612751565b61096b86868686868661281d565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612aee565b610a97896121c3565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad987878787878761281d565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250612751565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153b9565b9050610cc882612b87565b15610dc75780516000610cdc82600161541d565b67ffffffffffffffff811115610cf457610cf46152c1565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615435565b6020026020010151828281518110610d5757610d57615435565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615435565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615122565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d53565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ec05781600181610e9c670de0b6b3a764000085615464565b610ea6919061541d565b610eb091906154a1565b610eba91906154b8565b93508092505b5050935093915050565b610ed2611c7e565b610eda612203565b610ee3836121c3565b610eec826121c3565b610ef581613074565b82610f0081836130ae565b610f146001600160a01b03821684846133b8565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f5991815260200190565b60405180910390a350610f6c600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561104d57600080fd5b505af1158015611061573d6000803e3d6000fd5b50505050611070858585612d53565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110de57600080fd5b505af11580156110f2573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561115657600080fd5b505af115801561116a573d6000803e3d6000fd5b50505050611070858585611d55565b600061118760c95460021490565b156111be576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c88383613461565b611211576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b611246611c7e565b6112506000613551565b565b6112906040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250612751565b61070181613582565b60655433906001600160a01b0316811461131b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613551565b61132c611c7e565b611335816121c3565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113b961216e565b6113c2836121c3565b816001600160a01b0316836001600160a01b031614806113f35750806001600160a01b0316836001600160a01b0316145b1561142a576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611432612203565b61143f8a8a8a8a8a61225c565b9095509350611450888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b6114a9612203565b60006114b583836135cc565b905080156114c8576114c8838383613929565b506114d3600160c955565b5050565b6000808285856114e561216e565b6114ee836121c3565b816001600160a01b0316836001600160a01b0316148061151f5750806001600160a01b0316836001600160a01b0316145b15611556576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61155e612203565b61156b8a8a8a8a8a613dc5565b909550935061157c888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b61160b6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250612751565b61161361216e565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116b9576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156117145761170c878787848181106116da576116da615435565b90506020020160208101906116ef9190614db1565b86868581811061170157611701615435565b90506040020161184c565b6001016116bc565b50505050505050565b60008082858561172b61216e565b611734836121c3565b816001600160a01b0316836001600160a01b031614806117655750806001600160a01b0316836001600160a01b0316145b1561179c576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117a4612203565b6117b18a8a8a8a8a613e57565b90955093508884146117ef576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117fb888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b61186d6040518060600160405280603581526020016157ba60359139612751565b611876836121c3565b61187f826121c3565b6706f05b59d3b20000813511156118d3576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b0316148061190c57506118f6613f14565b6001600160a01b0316836001600160a01b031614155b80611954575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561195157611951615122565b14155b1561198b576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261199d60408301602084016154f3565b60038111156119ae576119ae615122565b1480156119bb5750803515155b156119f2576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002611a0460408301602084016154f3565b6003811115611a1557611a15615122565b1480611a4157506001611a2e60408301602084016154f3565b6003811115611a3f57611a3f615122565b145b8015611a56575060ff546001600160a01b0316155b15611a8d576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611afd91908a01908a016154f3565b604051611b0d9493929190615514565b60405180910390a36000611b2760408401602085016154f3565b6003811115611b3857611b38615122565b03611b95576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bef565b81358155611ba960408301602084016154f3565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611be957611be9615122565b02179055505b50505050565b611bfd611c7e565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c466033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611ce1816121c3565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d92576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611de657611de6615122565b6003811115611df757611df7615122565b9052509050600081602001516003811115611e1457611e14615122565b03611e4b576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190615545565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f609190615545565b835160ff54919250906001600160a01b031615801590612000575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612000919061555e565b15612009575060005b600061201d82670de0b6b3a764000061541d565b90508261202a8286615464565b61203491906154b8565b95508560018161204c670de0b6b3a76400008e615464565b612056919061541d565b61206091906154a1565b61206a91906154b8565b96505050505050935093915050565b6001600160a01b0381166120f55760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611250576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c954036122555760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b6000806122698585613fa0565b61227385886140c0565b9150612280828686610f71565b915050858110156122c7576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b6122d284848361420b565b9550959350505050565b60006122e784610c30565b6001600160a01b038516600090815261012d60205260408120549192509061231090849061541d565b905061231b81613074565b815160008080805b8481101561264357600061012e600089848151811061234457612344615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b031681526020019081526020016000205490508060001461263a576123a56001876154a1565b821015612405576123d18883815181106123c1576123c1615435565b60200260200101518c8b8a614285565b6123db908661541d565b9450866123e8828c615464565b6123f291906154b8565b93506123fe848461541d565b9250612500565b6000612411868b6154a1565b90508061012e60008b868151811061242b5761242b615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461248591906154a1565b925050819055508b6001600160a01b03168984815181106124a8576124a8615435565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce38836040516124ea91815260200190565b60405180910390a36124fc848c6154a1565b9450505b8b6001600160a01b031688838151811061251c5761251c615435565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af558760405161257d91815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125ae576125ae615435565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561262157600080fd5b505af1158015612635573d6000803e3d6000fd5b505050505b50600101612323565b5050505050505050505050565b600160c955565b612660816121c3565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6126dd816121c3565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab9061279d90339086906004016155d8565b602060405180830381865afa1580156127ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127de919061555e565b9050806114d3573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b939291906155fa565b84838114158061282d5750808214155b15612864576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612ae457600086868381811061288357612883615435565b90506020028101906128959190615626565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509394508892508791508590508181106128dd576128dd615435565b90506020028101906128ef9190615626565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508451835193945092831491506129629050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612ad55782818151811061297f5761297f615435565b602002602001015161013060008e8e8981811061299e5761299e615435565b90506020020160208101906129b39190614db1565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008684815181106129e7576129e7615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a3857612a38615435565b60200260200101516001600160a01b03168c8c87818110612a5b57612a5b615435565b9050602002016020810190612a709190614db1565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612aac57612aac615435565b6020026020010151604051612ac5911515815260200190565b60405180910390a3600101612965565b50836001019350505050612867565b5050505050505050565b600054610100900460ff16612b6b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612b748461435e565b612b7c6143ec565b611bef838383614471565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612be8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c1091908101906153b9565b805190915060005b81811015612d4b57828181518110612c3257612c32615435565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d0657846001600160a01b0316838281518110612c8e57612c8e615435565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf7919061568e565b6001600160a01b031614612d3c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d4b57600101612c18565b505050919050565b60008084600003612d90576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612de457612de4615122565b6003811115612df557612df5615122565b9052509050600081602001516003811115612e1257612e12615122565b03612e49576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ead573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed19190615545565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5e9190615545565b835160ff54919250906001600160a01b031615801590612ffe575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffe919061555e565b15613007575060005b600061301b82670de0b6b3a764000061541d565b905061302f670de0b6b3a764000084615464565b8161303a868d615464565b6130449190615464565b61304e91906154b8565b96508261305b8286615464565b61306591906154b8565b95505050505050935093915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561310e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131329190615545565b90508082111561316e576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d602052604081205461319290836154a1565b905082811015611bef5780830360006131aa86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b8281101561337e5761012e60008683815181106131ec576131ec615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133765761324a6001846154a1565b8110156132875761327685828151811061326657613266615435565b60200260200101518b8887614285565b613280908361541d565b9150613376565b600061329383886154a1565b90508061012e60008885815181106132ad576132ad615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461330791906154a1565b925050819055508a6001600160a01b031686838151811061332a5761332a615435565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161336c91815260200190565b60405180910390a3505b6001016131cd565b506001600160a01b038916600090815261012d6020526040812080548792906133a89084906154a1565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f6c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614536565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134ac576134a582612b87565b905061354b565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015613519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353d919061568e565b6001600160a01b0316141590505b92915050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556107018161461e565b61358b81613074565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b60006135d88383613461565b613621576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015613683573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a79190615545565b6001600160a01b038516600090815261012d602052604090205490915080821115613920576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff16156139205760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa158015613765573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137899190615545565b60fe549091506137a6906001600160a01b038681169116876133b8565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561380b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061382f9190615545565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac3537898961389a86866154a1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561390157600080fd5b505af1158015613915573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613933613f14565b60fe5460ff549192506001600160a01b03908116916000911615613db85760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156139c2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139ea91908101906156ab565b8151919350915060005b81811015613db357828181518110613a0e57613a0e615435565b602002602001015160000315613db3576000848281518110613a3257613a32615435565b60200260200101516001600160a01b0316636f1a30a8858481518110613a5a57613a5a615435565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613a9c939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ade9190615766565b91505088811115613aec5750875b613af6818b614688565b613b005750613db3565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b879190615545565b90508a6001600160a01b031663095ea7b3878581518110613baa57613baa615435565b6020026020010151846040518363ffffffff1660e01b8152600401613be49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c27919061555e565b50858381518110613c3a57613c3a615435565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ce89190615766565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d719190615545565b9050613d7d838c6154a1565b9a50613d8982826154a1565b613d93908961541d565b97508a600003613da557505050613db3565b8360010193505050506139f4565b505050505b61096b86848388886147c0565b600080613dd28585613fa0565b6000613ddf87878761107a565b91505087811115613e26576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e3086826140c0565b9250613e3d838787610f71565b9250613e4c905085858461420b565b509550959350505050565b600080613e648585613fa0565b6000613e7187878761107a565b915050613e7e86826140c0565b9250808314613eb9576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613efd576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f0885858961420b565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f9b919061568e565b905090565b60ff546000906001600160a01b03161580159061403d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015614019573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061403d919061555e565b905080158015614089575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff16600381111561408757614087615122565b145b15610f6c576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015614129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061414d9190615545565b60fe5490915061416c906001600160a01b03848116913391168761495e565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa1580156141d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141f59190615545565b905061420182826154a1565b9695505050505050565b6001600160a01b038316600090815261012d60205260409020548181101561425f576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61426984836149af565b8361427e6001600160a01b03821685856133b8565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142bb908590615464565b6142c591906154b8565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143029084906154a1565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161434e91815260200190565b60405180910390a3949350505050565b600054610100900460ff166143db5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6143e36149e1565b61070181614a66565b600054610100900460ff166144695760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614ae3565b600054610100900460ff166144ee5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6144f7836126d4565b61450082611cd8565b61450981613582565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b600061458b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b609092919063ffffffff16565b90508051600014806145ac5750808060200190518101906145ac919061555e565b610f6c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b1580156146e957600080fd5b505af11580156146fd573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa158015614771573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147959190615545565b61479f9190615464565b6147a991906154b8565b905060fb5481106147b957600191505b5092915050565b82156148975760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b15801561487e57600080fd5b505af1158015614892573d6000803e3d6000fd5b505050505b801561427e576001600160a01b038216600090815261012d6020526040812080548392906148c690849061541d565b90915550506001600160a01b03808616600090815261012e602090815260408083209386168352929052908120805483929061490390849061541d565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161494f91815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bef9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016133fd565b6001600160a01b038216600090815261012d6020526040812080548392906149d89084906154a1565b90915550505050565b600054610100900460ff16614a5e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614b79565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126505760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614b6f8484600085614bff565b90505b9392505050565b600054610100900460ff16614bf65760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61125033613551565b606082471015614c775760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614c93919061578a565b60006040518083038185875af1925050503d8060008114614cd0576040519150601f19603f3d011682016040523d82523d6000602084013e614cd5565b606091505b5091509150614ce687838387614cf3565b925050505b949350505050565b60608315614d62578251600003614d5b576001600160a01b0385163b614d5b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614ceb565b614ceb8383815115614d775781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157a6565b6001600160a01b038116811461070157600080fd5b8035610dc781614d91565b600060208284031215614dc357600080fd5b8135614b7281614d91565b600080600060608486031215614de357600080fd5b833592506020840135614df581614d91565b91506040840135614e0581614d91565b809150509250925092565b600080600080600060a08688031215614e2857600080fd5b85359450602086013593506040860135614e4181614d91565b92506060860135614e5181614d91565b91506080860135614e6181614d91565b809150509295509295909350565b60008060408385031215614e8257600080fd5b8235614e8d81614d91565b91506020830135614e9d81614d91565b809150509250929050565b60008083601f840112614eba57600080fd5b50813567ffffffffffffffff811115614ed257600080fd5b6020830191508360208260051b8501011115614eed57600080fd5b9250929050565b60008060008060008060608789031215614f0d57600080fd5b863567ffffffffffffffff80821115614f2557600080fd5b614f318a838b01614ea8565b90985096506020890135915080821115614f4a57600080fd5b614f568a838b01614ea8565b90965094506040890135915080821115614f6f57600080fd5b50614f7c89828a01614ea8565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fb057600080fd5b614fb98c614da6565b9a50614fc760208d01614da6565b9950614fd560408d01614da6565b9850614fe360608d01614da6565b975060808c0135965067ffffffffffffffff8060a08e0135111561500657600080fd5b6150168e60a08f01358f01614ea8565b909750955060c08d013581101561502c57600080fd5b61503c8e60c08f01358f01614ea8565b909550935060e08d013581101561505257600080fd5b506150638d60e08e01358e01614ea8565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150bc5783516001600160a01b031683529284019291840191600101615097565b50909695505050505050565b6000806000606084860312156150dd57600080fd5b83356150e881614d91565b925060208401356150f881614d91565b929592945050506040919091013590565b60006020828403121561511b57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110615188577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614b726020830184615151565b6000806000806000606086880312156151b857600080fd5b85356151c381614d91565b9450602086013567ffffffffffffffff808211156151e057600080fd5b6151ec89838a01614ea8565b9096509450604088013591508082111561520557600080fd5b818801915088601f83011261521957600080fd5b81358181111561522857600080fd5b8960208260061b850101111561523d57600080fd5b9699959850939650602001949392505050565b6000806000838503608081121561526657600080fd5b843561527181614d91565b9350602085013561528181614d91565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152b357600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715615319576153196152c1565b604052919050565b600067ffffffffffffffff82111561533b5761533b6152c1565b5060051b60200190565b600082601f83011261535657600080fd5b8151602061536b61536683615321565b6152f0565b82815260059290921b8401810191818101908684111561538a57600080fd5b8286015b848110156153ae5780516153a181614d91565b835291830191830161538e565b509695505050505050565b6000602082840312156153cb57600080fd5b815167ffffffffffffffff8111156153e257600080fd5b614ceb84828501615345565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615430576154306153ee565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561549c5761549c6153ee565b500290565b6000828210156154b3576154b36153ee565b500390565b6000826154ee577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561550557600080fd5b813560048110614b7257600080fd5b848152602081018490526080810161552f6040830185615151565b61553c6060830184615151565b95945050505050565b60006020828403121561555757600080fd5b5051919050565b60006020828403121561557057600080fd5b81518015158114614b7257600080fd5b60005b8381101561559b578181015183820152602001615583565b83811115611bef5750506000910152565b600081518084526155c4816020860160208601615580565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614b6f60408301846155ac565b60006001600160a01b0380861683528085166020840152506060604083015261553c60608301846155ac565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261565b57600080fd5b83018035915067ffffffffffffffff82111561567657600080fd5b6020019150600581901b3603821315614eed57600080fd5b6000602082840312156156a057600080fd5b8151614b7281614d91565b600080604083850312156156be57600080fd5b825167ffffffffffffffff808211156156d657600080fd5b6156e286838701615345565b93506020915081850151818111156156f957600080fd5b85019050601f8101861361570c57600080fd5b805161571a61536682615321565b81815260059190911b8201830190838101908883111561573957600080fd5b928401925b828410156157575783518252928401929084019061573e565b80955050505050509250929050565b6000806040838503121561577957600080fd5b505080516020909101519092909150565b6000825161579c818460208701615580565b9190910192915050565b602081526000614b7260208301846155ac56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a26469706673582212200c4c1be8186609d8812933be8513b877d4d7456c543e250549bac4e27cafee1364736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614db1565b6106f0565b005b61037b610376366004614dce565b610704565b60408051928352602083019190915201610315565b61036661039e366004614db1565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e10565b6107d0565b610343610425366004614e6f565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614db1565b61091a565b610366610467366004614db1565b61092b565b61036661047a366004614ef4565b61093c565b61036661048d366004614f8e565b610973565b610366610b4a565b6104ad6104a8366004614db1565b610c30565b604051610315919061507b565b61037b6104c8366004614dce565b610dcc565b6103666104db3660046150c8565b610eca565b61037b6104ee366004614dce565b610f71565b61037b610501366004614dce565b61107a565b610519610514366004614e6f565b611179565b604051908152602001610315565b610519610535366004614db1565b6001600160a01b0316600090815261012d602052604090205490565b61036661123e565b610366610567366004615109565b611252565b610366611299565b610366610582366004614db1565b611324565b6033546001600160a01b0316610301565b61037b6105a6366004614e10565b6113ab565b6103666105b9366004614e6f565b6114a1565b61012f54610301906001600160a01b031681565b6106076105e0366004614e6f565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b60405161031592919061518c565b6097546001600160a01b0316610301565b61037b610634366004614e10565b6114d7565b6103666115cd565b61036661064f3660046151a0565b61167f565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e10565b61171d565b6103666106a8366004615250565b61184c565b6103666106bb366004614db1565b611bf5565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c7e565b61070181611cd8565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615122565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d55565b508092505050935093915050565b6107c7611c7e565b61070181612079565b6000808285856107de61216e565b6107e7836121c3565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610857612203565b6108648a8a8a8a8a61225c565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c7e565b61070181612657565b610933611c7e565b610701816126d4565b61095d6040518060600160405280603c81526020016157ef603c9139612751565b61096b86868686868661281d565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612aee565b610a97896121c3565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad987878787878761281d565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250612751565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153b9565b9050610cc882612b87565b15610dc75780516000610cdc82600161541d565b67ffffffffffffffff811115610cf457610cf46152c1565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615435565b6020026020010151828281518110610d5757610d57615435565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615435565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615122565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d53565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ec05781600181610e9c670de0b6b3a764000085615464565b610ea6919061541d565b610eb091906154a1565b610eba91906154b8565b93508092505b5050935093915050565b610ed2611c7e565b610eda612203565b610ee3836121c3565b610eec826121c3565b610ef581613074565b82610f0081836130ae565b610f146001600160a01b03821684846133b8565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f5991815260200190565b60405180910390a350610f6c600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561104d57600080fd5b505af1158015611061573d6000803e3d6000fd5b50505050611070858585612d53565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110de57600080fd5b505af11580156110f2573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561115657600080fd5b505af115801561116a573d6000803e3d6000fd5b50505050611070858585611d55565b600061118760c95460021490565b156111be576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c88383613461565b611211576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b611246611c7e565b6112506000613551565b565b6112906040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250612751565b61070181613582565b60655433906001600160a01b0316811461131b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613551565b61132c611c7e565b611335816121c3565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113b961216e565b6113c2836121c3565b816001600160a01b0316836001600160a01b031614806113f35750806001600160a01b0316836001600160a01b0316145b1561142a576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611432612203565b61143f8a8a8a8a8a61225c565b9095509350611450888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b6114a9612203565b60006114b583836135cc565b905080156114c8576114c8838383613929565b506114d3600160c955565b5050565b6000808285856114e561216e565b6114ee836121c3565b816001600160a01b0316836001600160a01b0316148061151f5750806001600160a01b0316836001600160a01b0316145b15611556576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61155e612203565b61156b8a8a8a8a8a613dc5565b909550935061157c888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b61160b6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250612751565b61161361216e565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116b9576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156117145761170c878787848181106116da576116da615435565b90506020020160208101906116ef9190614db1565b86868581811061170157611701615435565b90506040020161184c565b6001016116bc565b50505050505050565b60008082858561172b61216e565b611734836121c3565b816001600160a01b0316836001600160a01b031614806117655750806001600160a01b0316836001600160a01b0316145b1561179c576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117a4612203565b6117b18a8a8a8a8a613e57565b90955093508884146117ef576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117fb888887876122dc565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b61186d6040518060600160405280603581526020016157ba60359139612751565b611876836121c3565b61187f826121c3565b6706f05b59d3b20000813511156118d3576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b0316148061190c57506118f6613f14565b6001600160a01b0316836001600160a01b031614155b80611954575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561195157611951615122565b14155b1561198b576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261199d60408301602084016154f3565b60038111156119ae576119ae615122565b1480156119bb5750803515155b156119f2576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002611a0460408301602084016154f3565b6003811115611a1557611a15615122565b1480611a4157506001611a2e60408301602084016154f3565b6003811115611a3f57611a3f615122565b145b8015611a56575060ff546001600160a01b0316155b15611a8d576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611afd91908a01908a016154f3565b604051611b0d9493929190615514565b60405180910390a36000611b2760408401602085016154f3565b6003811115611b3857611b38615122565b03611b95576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bef565b81358155611ba960408301602084016154f3565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611be957611be9615122565b02179055505b50505050565b611bfd611c7e565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c466033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611ce1816121c3565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d92576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611de657611de6615122565b6003811115611df757611df7615122565b9052509050600081602001516003811115611e1457611e14615122565b03611e4b576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190615545565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f609190615545565b835160ff54919250906001600160a01b031615801590612000575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612000919061555e565b15612009575060005b600061201d82670de0b6b3a764000061541d565b90508261202a8286615464565b61203491906154b8565b95508560018161204c670de0b6b3a76400008e615464565b612056919061541d565b61206091906154a1565b61206a91906154b8565b96505050505050935093915050565b6001600160a01b0381166120f55760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611250576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c954036122555760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b6000806122698585613fa0565b61227385886140c0565b9150612280828686610f71565b915050858110156122c7576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b6122d284848361420b565b9550959350505050565b60006122e784610c30565b6001600160a01b038516600090815261012d60205260408120549192509061231090849061541d565b905061231b81613074565b815160008080805b8481101561264357600061012e600089848151811061234457612344615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b031681526020019081526020016000205490508060001461263a576123a56001876154a1565b821015612405576123d18883815181106123c1576123c1615435565b60200260200101518c8b8a614285565b6123db908661541d565b9450866123e8828c615464565b6123f291906154b8565b93506123fe848461541d565b9250612500565b6000612411868b6154a1565b90508061012e60008b868151811061242b5761242b615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461248591906154a1565b925050819055508b6001600160a01b03168984815181106124a8576124a8615435565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce38836040516124ea91815260200190565b60405180910390a36124fc848c6154a1565b9450505b8b6001600160a01b031688838151811061251c5761251c615435565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af558760405161257d91815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125ae576125ae615435565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561262157600080fd5b505af1158015612635573d6000803e3d6000fd5b505050505b50600101612323565b5050505050505050505050565b600160c955565b612660816121c3565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6126dd816121c3565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab9061279d90339086906004016155d8565b602060405180830381865afa1580156127ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127de919061555e565b9050806114d3573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b939291906155fa565b84838114158061282d5750808214155b15612864576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612ae457600086868381811061288357612883615435565b90506020028101906128959190615626565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509394508892508791508590508181106128dd576128dd615435565b90506020028101906128ef9190615626565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508451835193945092831491506129629050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612ad55782818151811061297f5761297f615435565b602002602001015161013060008e8e8981811061299e5761299e615435565b90506020020160208101906129b39190614db1565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008684815181106129e7576129e7615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a3857612a38615435565b60200260200101516001600160a01b03168c8c87818110612a5b57612a5b615435565b9050602002016020810190612a709190614db1565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612aac57612aac615435565b6020026020010151604051612ac5911515815260200190565b60405180910390a3600101612965565b50836001019350505050612867565b5050505050505050565b600054610100900460ff16612b6b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612b748461435e565b612b7c6143ec565b611bef838383614471565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612be8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c1091908101906153b9565b805190915060005b81811015612d4b57828181518110612c3257612c32615435565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d0657846001600160a01b0316838281518110612c8e57612c8e615435565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf7919061568e565b6001600160a01b031614612d3c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d4b57600101612c18565b505050919050565b60008084600003612d90576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612de457612de4615122565b6003811115612df557612df5615122565b9052509050600081602001516003811115612e1257612e12615122565b03612e49576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ead573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed19190615545565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5e9190615545565b835160ff54919250906001600160a01b031615801590612ffe575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffe919061555e565b15613007575060005b600061301b82670de0b6b3a764000061541d565b905061302f670de0b6b3a764000084615464565b8161303a868d615464565b6130449190615464565b61304e91906154b8565b96508261305b8286615464565b61306591906154b8565b95505050505050935093915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561310e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131329190615545565b90508082111561316e576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d602052604081205461319290836154a1565b905082811015611bef5780830360006131aa86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b8281101561337e5761012e60008683815181106131ec576131ec615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133765761324a6001846154a1565b8110156132875761327685828151811061326657613266615435565b60200260200101518b8887614285565b613280908361541d565b9150613376565b600061329383886154a1565b90508061012e60008885815181106132ad576132ad615435565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461330791906154a1565b925050819055508a6001600160a01b031686838151811061332a5761332a615435565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161336c91815260200190565b60405180910390a3505b6001016131cd565b506001600160a01b038916600090815261012d6020526040812080548792906133a89084906154a1565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f6c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614536565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134ac576134a582612b87565b905061354b565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015613519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353d919061568e565b6001600160a01b0316141590505b92915050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556107018161461e565b61358b81613074565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b60006135d88383613461565b613621576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015613683573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a79190615545565b6001600160a01b038516600090815261012d602052604090205490915080821115613920576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff16156139205760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa158015613765573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137899190615545565b60fe549091506137a6906001600160a01b038681169116876133b8565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561380b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061382f9190615545565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac3537898961389a86866154a1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561390157600080fd5b505af1158015613915573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613933613f14565b60fe5460ff549192506001600160a01b03908116916000911615613db85760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156139c2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139ea91908101906156ab565b8151919350915060005b81811015613db357828181518110613a0e57613a0e615435565b602002602001015160000315613db3576000848281518110613a3257613a32615435565b60200260200101516001600160a01b0316636f1a30a8858481518110613a5a57613a5a615435565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613a9c939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ade9190615766565b91505088811115613aec5750875b613af6818b614688565b613b005750613db3565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b879190615545565b90508a6001600160a01b031663095ea7b3878581518110613baa57613baa615435565b6020026020010151846040518363ffffffff1660e01b8152600401613be49291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c27919061555e565b50858381518110613c3a57613c3a615435565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ce89190615766565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d719190615545565b9050613d7d838c6154a1565b9a50613d8982826154a1565b613d93908961541d565b97508a600003613da557505050613db3565b8360010193505050506139f4565b505050505b61096b86848388886147c0565b600080613dd28585613fa0565b6000613ddf87878761107a565b91505087811115613e26576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e3086826140c0565b9250613e3d838787610f71565b9250613e4c905085858461420b565b509550959350505050565b600080613e648585613fa0565b6000613e7187878761107a565b915050613e7e86826140c0565b9250808314613eb9576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613efd576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f0885858961420b565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f9b919061568e565b905090565b60ff546000906001600160a01b03161580159061403d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015614019573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061403d919061555e565b905080158015614089575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff16600381111561408757614087615122565b145b15610f6c576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015614129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061414d9190615545565b60fe5490915061416c906001600160a01b03848116913391168761495e565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa1580156141d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141f59190615545565b905061420182826154a1565b9695505050505050565b6001600160a01b038316600090815261012d60205260409020548181101561425f576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61426984836149af565b8361427e6001600160a01b03821685856133b8565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142bb908590615464565b6142c591906154b8565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143029084906154a1565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161434e91815260200190565b60405180910390a3949350505050565b600054610100900460ff166143db5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6143e36149e1565b61070181614a66565b600054610100900460ff166144695760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614ae3565b600054610100900460ff166144ee5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6144f7836126d4565b61450082611cd8565b61450981613582565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b600061458b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b609092919063ffffffff16565b90508051600014806145ac5750808060200190518101906145ac919061555e565b610f6c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b1580156146e957600080fd5b505af11580156146fd573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa158015614771573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147959190615545565b61479f9190615464565b6147a991906154b8565b905060fb5481106147b957600191505b5092915050565b82156148975760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b15801561487e57600080fd5b505af1158015614892573d6000803e3d6000fd5b505050505b801561427e576001600160a01b038216600090815261012d6020526040812080548392906148c690849061541d565b90915550506001600160a01b03808616600090815261012e602090815260408083209386168352929052908120805483929061490390849061541d565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161494f91815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bef9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016133fd565b6001600160a01b038216600090815261012d6020526040812080548392906149d89084906154a1565b90915550505050565b600054610100900460ff16614a5e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611250614b79565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126505760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614b6f8484600085614bff565b90505b9392505050565b600054610100900460ff16614bf65760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61125033613551565b606082471015614c775760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614c93919061578a565b60006040518083038185875af1925050503d8060008114614cd0576040519150601f19603f3d011682016040523d82523d6000602084013e614cd5565b606091505b5091509150614ce687838387614cf3565b925050505b949350505050565b60608315614d62578251600003614d5b576001600160a01b0385163b614d5b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614ceb565b614ceb8383815115614d775781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157a6565b6001600160a01b038116811461070157600080fd5b8035610dc781614d91565b600060208284031215614dc357600080fd5b8135614b7281614d91565b600080600060608486031215614de357600080fd5b833592506020840135614df581614d91565b91506040840135614e0581614d91565b809150509250925092565b600080600080600060a08688031215614e2857600080fd5b85359450602086013593506040860135614e4181614d91565b92506060860135614e5181614d91565b91506080860135614e6181614d91565b809150509295509295909350565b60008060408385031215614e8257600080fd5b8235614e8d81614d91565b91506020830135614e9d81614d91565b809150509250929050565b60008083601f840112614eba57600080fd5b50813567ffffffffffffffff811115614ed257600080fd5b6020830191508360208260051b8501011115614eed57600080fd5b9250929050565b60008060008060008060608789031215614f0d57600080fd5b863567ffffffffffffffff80821115614f2557600080fd5b614f318a838b01614ea8565b90985096506020890135915080821115614f4a57600080fd5b614f568a838b01614ea8565b90965094506040890135915080821115614f6f57600080fd5b50614f7c89828a01614ea8565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fb057600080fd5b614fb98c614da6565b9a50614fc760208d01614da6565b9950614fd560408d01614da6565b9850614fe360608d01614da6565b975060808c0135965067ffffffffffffffff8060a08e0135111561500657600080fd5b6150168e60a08f01358f01614ea8565b909750955060c08d013581101561502c57600080fd5b61503c8e60c08f01358f01614ea8565b909550935060e08d013581101561505257600080fd5b506150638d60e08e01358e01614ea8565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150bc5783516001600160a01b031683529284019291840191600101615097565b50909695505050505050565b6000806000606084860312156150dd57600080fd5b83356150e881614d91565b925060208401356150f881614d91565b929592945050506040919091013590565b60006020828403121561511b57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110615188577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614b726020830184615151565b6000806000806000606086880312156151b857600080fd5b85356151c381614d91565b9450602086013567ffffffffffffffff808211156151e057600080fd5b6151ec89838a01614ea8565b9096509450604088013591508082111561520557600080fd5b818801915088601f83011261521957600080fd5b81358181111561522857600080fd5b8960208260061b850101111561523d57600080fd5b9699959850939650602001949392505050565b6000806000838503608081121561526657600080fd5b843561527181614d91565b9350602085013561528181614d91565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152b357600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715615319576153196152c1565b604052919050565b600067ffffffffffffffff82111561533b5761533b6152c1565b5060051b60200190565b600082601f83011261535657600080fd5b8151602061536b61536683615321565b6152f0565b82815260059290921b8401810191818101908684111561538a57600080fd5b8286015b848110156153ae5780516153a181614d91565b835291830191830161538e565b509695505050505050565b6000602082840312156153cb57600080fd5b815167ffffffffffffffff8111156153e257600080fd5b614ceb84828501615345565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615430576154306153ee565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561549c5761549c6153ee565b500290565b6000828210156154b3576154b36153ee565b500390565b6000826154ee577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561550557600080fd5b813560048110614b7257600080fd5b848152602081018490526080810161552f6040830185615151565b61553c6060830184615151565b95945050505050565b60006020828403121561555757600080fd5b5051919050565b60006020828403121561557057600080fd5b81518015158114614b7257600080fd5b60005b8381101561559b578181015183820152602001615583565b83811115611bef5750506000910152565b600081518084526155c4816020860160208601615580565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614b6f60408301846155ac565b60006001600160a01b0380861683528085166020840152506060604083015261553c60608301846155ac565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261565b57600080fd5b83018035915067ffffffffffffffff82111561567657600080fd5b6020019150600581901b3603821315614eed57600080fd5b6000602082840312156156a057600080fd5b8151614b7281614d91565b600080604083850312156156be57600080fd5b825167ffffffffffffffff808211156156d657600080fd5b6156e286838701615345565b93506020915081850151818111156156f957600080fd5b85019050601f8101861361570c57600080fd5b805161571a61536682615321565b81815260059190911b8201830190838101908883111561573957600080fd5b928401925b828410156157575783518252928401929084019061573e565b80955050505050509250929050565b6000806040838503121561577957600080fd5b505080516020909101519092909150565b6000825161579c818460208701615580565b9190910192915050565b602081526000614b7260208301846155ac56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a26469706673582212200c4c1be8186609d8812933be8513b877d4d7456c543e250549bac4e27cafee1364736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "91b55240df7761b1edcdbbc6fc102117", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vBNB_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidArguments\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"MarketNotExistInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetsReservesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"name\":\"PoolAssetsDirectTransferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPoolRegistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPoolRegistry\",\"type\":\"address\"}],\"name\":\"PoolRegistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_COMPTROLLER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NATIVE_WRAPPED\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VBNB\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolAssetReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"getPools\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"poolsWithCore\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolsAssetsDirectTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"comptrollers\",\"type\":\"address[]\"},{\"internalType\":\"address[][]\",\"name\":\"assets\",\"type\":\"address[][]\"},{\"internalType\":\"bool[][]\",\"name\":\"values\",\"type\":\"bool[][]\"}],\"name\":\"setPoolsAssetsDirectTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"errors\":{\"ReentrancyGuardError()\":[{\"details\":\"This error is used to safeguard against reentrancy attacks, ensuring that a certain operation cannot be called recursively within the same transaction.\"}]},\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Reserves of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"corePoolComptroller_\":\"Address of the Comptroller pool\",\"nativeWrapped_\":\"Address of the wrapped native currency\",\"vBNB_\":\"Address of the vBNB\"}},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getPoolAssetReserve(address,address)\":{\"custom:error\":\"MarketNotExistInPool When asset does not exist in the pool(comptroller)ReentrancyGuardError thrown to prevent reentrancy during the function execution\",\"details\":\"Get the Amount of the asset in the risk fund for the specific pool\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"},\"returns\":{\"reserves\":\"Asset's reserve in risk fund\"}},\"getPools(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"poolsWithCore\":\"Array of the pools addresses in which token is available\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256,address[],address[][],bool[][])\":{\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"minimum amount to convert\",\"poolRegistry_\":\"Address of the pool registry\",\"priceOracle_\":\"Resilient oracle address\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPoolRegistry(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"custom:event\":\"PoolRegistryUpdated emits on success\",\"details\":\"Pool registry setter\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"custom:access\":\"Restricted by ACM\",\"custom:event\":\"PoolAssetsDirectTransferUpdated emits on success\",\"params\":{\"assets\":\"Addresses of the assets need to be added for direct transfer\",\"comptrollers\":\"Addresses of the pools\",\"values\":\"Boolean value to indicate whether direct transfer is allowed for each asset.\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"stateVariables\":{\"CORE_POOL_COMPTROLLER\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"NATIVE_WRAPPED\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"VBNB\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\",\"details\":\"This address is used to include the BNB market while in getPools method\"},\"poolsAssetsDirectTransfer\":{\"details\":\"Comptroller(pool) -> Asset -> bool(should transfer directly on true)\"},\"poolsAssetsReserves\":{\"details\":\"Comptroller(pool) -> Asset -> amount\"}},\"title\":\"RiskFundConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"MarketNotExistInPool(address,address)\":[{\"notice\":\"thrown when asset does not exist in the pool\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"ReentrancyGuardError()\":[{\"notice\":\"thrown to prevent reentrancy\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Emitted after updating of the assets reserves amount -> reserve increased by amount\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDirectTransferUpdated(address,address,bool)\":{\"notice\":\"Emitted after the poolsAssetsDirectTransfer mapping is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_COMPTROLLER()\":{\"notice\":\"Address of the core pool comptroller\"},\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"NATIVE_WRAPPED()\":{\"notice\":\"Address of the native wrapped currency\"},\"VBNB()\":{\"notice\":\"Address of the vBNB\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\"},\"getPools(address)\":{\"notice\":\"Get the array of all pools addresses\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"poolRegistry()\":{\"notice\":\"Address of pool registry contract\"},\"poolsAssetsDirectTransfer(address,address)\":{\"notice\":\"The mapping contains the assets for each pool which are sent to RiskFund directly\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\":{\"notice\":\"Update the poolsAssetsDirectTransfer mapping\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"RiskFundConverter used for token conversions and sends received token to RiskFund\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/RiskFundConverter.sol\":\"RiskFundConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IComptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IComptroller {\\n function isComptroller() external view returns (bool);\\n\\n function markets(address) external view returns (bool);\\n\\n function getAllMarkets() external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x7d85db8d34103352b25f29f591c1e45159222f0d2bbafaa3fcd42f42bf9a523d\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IPoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IPoolRegistry {\\n /// @notice Get VToken in the Pool for an Asset\\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\\n\\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb38a3b61926e55588096e0657b758b178130386143a5658030d659038ec7075c\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IVToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IVToken {\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x0718e50835da441b2dddcf6d52a671c43d386b96dbcc9eb41d68c3647b82c117\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa = _divRoundingUp(maxTokenOutReserve * EXP_SCALE, tokenInToOutConversion);\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa = (amountInMantissa * tokenInToOutConversion) / (EXP_SCALE);\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n\\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\\n converterNetwork.isTokenConverter(msg.sender);\\n if (isPrivateConversion) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n if (isPrivateConversion) {\\n amountInMantissa =\\n (amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) /\\n (tokenInUnderlyingPrice * conversionWithIncentive);\\n } else {\\n amountInMantissa = _divRoundingUp(\\n amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE,\\n tokenInUnderlyingPrice * conversionWithIncentive\\n );\\n }\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n\\n /// @dev Performs division where the result is rounded up\\n /// @param numerator The numerator of the division operation\\n /// @param denominator The denominator of the division operation. Must be non-zero\\n /// @return The result of the division, rounded up\\n function _divRoundingUp(uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return (numerator + denominator - 1) / denominator;\\n }\\n}\\n\",\"keccak256\":\"0x3a55b64cf2b9fe6872bffa9eabfbeef0a836227a0e8b588d813ae856771a40e9\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/RiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\nimport { IPoolRegistry } from \\\"../Interfaces/IPoolRegistry.sol\\\";\\nimport { IComptroller } from \\\"../Interfaces/IComptroller.sol\\\";\\nimport { IRiskFund, IRiskFundGetters } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IVToken } from \\\"../Interfaces/IVToken.sol\\\";\\n\\n/// @title RiskFundConverter\\n/// @author Venus\\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the core pool comptroller\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable CORE_POOL_COMPTROLLER;\\n\\n ///@notice Address of the vBNB\\n ///@dev This address is used to include the BNB market while in getPools method\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable VBNB;\\n\\n ///@notice Address of the native wrapped currency\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable NATIVE_WRAPPED;\\n\\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\\n mapping(address => uint256) internal assetsReserves;\\n\\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\\n /// @dev Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\\n\\n /// @notice Address of pool registry contract\\n address public poolRegistry;\\n\\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\\n\\n /// @notice Emitted when pool registry address is updated\\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\\n\\n /// @notice Emitted after updating of the assets reserves\\n /// amount -> reserve increased by amount\\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\\n\\n // Error thrown when comptrollers array length is not equal to assets array length\\n error InvalidArguments();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice thrown when asset does not exist in the pool\\n error MarketNotExistInPool(address comptroller, address asset);\\n\\n /// @notice thrown to prevent reentrancy\\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\\n /// cannot be called recursively within the same transaction.\\n error ReentrancyGuardError();\\n\\n /// @param corePoolComptroller_ Address of the Comptroller pool\\n /// @param vBNB_ Address of the vBNB\\n /// @param nativeWrapped_ Address of the wrapped native currency\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address corePoolComptroller_,\\n address vBNB_,\\n address nativeWrapped_\\n ) {\\n ensureNonzeroAddress(corePoolComptroller_);\\n ensureNonzeroAddress(vBNB_);\\n ensureNonzeroAddress(nativeWrapped_);\\n\\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\\n VBNB = vBNB_;\\n NATIVE_WRAPPED = nativeWrapped_;\\n\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param poolRegistry_ Address of the pool registry\\n /// @param minAmountToConvert_ minimum amount to convert\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address poolRegistry_,\\n uint256 minAmountToConvert_,\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) public initializer {\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n ensureNonzeroAddress(poolRegistry_);\\n poolRegistry = poolRegistry_;\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Pool registry setter\\n /// @param poolRegistry_ Address of the pool registry\\n /// @custom:event PoolRegistryUpdated emits on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:access Only Governance\\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\\n ensureNonzeroAddress(poolRegistry_);\\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\\n poolRegistry = poolRegistry_;\\n }\\n\\n /// @notice Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:access Restricted by ACM\\n function setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) external {\\n _checkAccessAllowed(\\\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\\\");\\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\\n }\\n\\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return reserves Asset's reserve in risk fund\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n reserves = poolsAssetsReserves[comptroller][asset];\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Reserves of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n tokenBalance = assetsReserves[tokenAddress];\\n }\\n\\n /// @notice Get the array of all pools addresses\\n /// @param tokenAddress Address of the token\\n /// @return poolsWithCore Array of the pools addresses in which token is available\\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\\n\\n if (isAssetListedInCore(tokenAddress)) {\\n uint256 poolsLength = poolsWithCore.length;\\n address[] memory extendedPools = new address[](poolsLength + 1);\\n\\n for (uint256 i; i < poolsLength; ) {\\n extendedPools[i] = poolsWithCore[i];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\\n poolsWithCore = extendedPools;\\n }\\n }\\n\\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\\n assetsReserves[tokenOutAddress] -= amountOut;\\n }\\n\\n /// @notice Hook to perform after converting tokens\\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\\n /// @param tokenInAddress Address of the tokenIn\\n /// @param tokenOutAddress Address of the tokenOut\\n /// @param amountIn Amount of tokenIn transferred\\n /// @param amountOut Amount of tokenOut transferred\\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\\n function _postConversionHook(\\n address tokenInAddress,\\n address tokenOutAddress,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal override {\\n address[] memory pools = getPools(tokenOutAddress);\\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\\n ensureNonzeroValue(assetReserve);\\n\\n uint256 poolsLength = pools.length;\\n uint256 distributedOutShare;\\n uint256 poolAmountInShare;\\n uint256 distributedInShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\\n if (currentPoolsAssetsReserves != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\\n distributedInShare += poolAmountInShare;\\n } else {\\n uint256 distributedDiff = amountOut - distributedOutShare;\\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\\n poolAmountInShare = amountIn - distributedInShare;\\n }\\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n\\n address[] memory pools = getPools(tokenAddress);\\n uint256 assetReserve = assetsReserves[tokenAddress];\\n uint256 poolsLength = pools.length;\\n uint256 distributedShare;\\n\\n for (uint256 i; i < poolsLength; ) {\\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\\n if (i < (poolsLength - 1)) {\\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\\n } else {\\n uint256 distributedDiff = amountDiff - distributedShare;\\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n assetsReserves[tokenAddress] -= amountDiff;\\n }\\n }\\n\\n /// @dev Update the poolAssetsReserves upon transferring the tokens\\n /// @param pool Address of the pool\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @param assetReserve Asset's reserve for the pool\\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\\n /// @custom:event AssetsReservesUpdated emits on success\\n function updatePoolAssetsReserve(\\n address pool,\\n address tokenAddress,\\n uint256 amount,\\n uint256 assetReserve\\n ) internal returns (uint256 poolAmountShare) {\\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\\n }\\n\\n /// @dev Update the poolsAssetsDirectTransfer mapping\\n /// @param comptrollers Addresses of the pools\\n /// @param assets Addresses of the assets need to be added for direct transfer\\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\\n function _setPoolsAssetsDirectTransfer(\\n address[] calldata comptrollers,\\n address[][] calldata assets,\\n bool[][] calldata values\\n ) internal {\\n uint256 comptrollersLength = comptrollers.length;\\n\\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 i; i < comptrollersLength; ) {\\n address[] memory poolAssets = assets[i];\\n bool[] memory assetsValues = values[i];\\n uint256 poolAssetsLength = poolAssets.length;\\n\\n if (poolAssetsLength != assetsValues.length) {\\n revert InvalidArguments();\\n }\\n\\n for (uint256 j; j < poolAssetsLength; ) {\\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\\n unchecked {\\n ++j;\\n }\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// and transferring funds to the protocol share reserve\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return balanceDifference Amount of asset, for _privateConversion\\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\\n function _updateAssetsState(address comptroller, address asset)\\n internal\\n override\\n returns (uint256 balanceDifference)\\n {\\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 currentBalance = token.balanceOf(address(this));\\n uint256 assetReserve = assetsReserves[asset];\\n if (currentBalance > assetReserve) {\\n unchecked {\\n balanceDifference = currentBalance - assetReserve;\\n }\\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\\n token.safeTransfer(destinationAddress, balanceDifference);\\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\\n\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\\n IRiskFund(destinationAddress).updatePoolState(\\n comptroller,\\n asset,\\n newDestinationBalance - previousDestinationBalance\\n );\\n balanceDifference = 0;\\n }\\n }\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal override {\\n if (convertedTokenInBalance > 0) {\\n emit AssetTransferredToDestination(\\n destinationAddress,\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance\\n );\\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\\n }\\n if (convertedTokenOutBalance > 0) {\\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed in core pool or not\\n /// @param tokenAddress Address of the asset\\n /// @return isAssetListed true if the asset is listed\\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\\n\\n uint256 coreMarketsLength = coreMarkets.length;\\n for (uint256 i; i < coreMarketsLength; ) {\\n isAssetListed = (VBNB == coreMarkets[i])\\n ? (tokenAddress == NATIVE_WRAPPED)\\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\\n\\n if (isAssetListed) {\\n break;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev This function checks for the given asset is listed or not\\n /// @param comptroller Address of the comptroller\\n /// @param asset Address of the asset\\n /// @return isListed true if the asset is listed\\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\\n if (comptroller == CORE_POOL_COMPTROLLER) {\\n isListed = isAssetListedInCore(asset);\\n } else {\\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n }\\n\\n /// @dev Get base asset address of the RiskFund\\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\\n }\\n}\\n\",\"keccak256\":\"0xa9fda55440f25049f1946980b801723cf2111584253a1c11ac1bb7d773cbe39e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162005ac638038062005ac683398101604081905262000034916200018a565b6200003f8362000081565b6200004a8262000081565b620000558162000081565b6001600160a01b0380841660805282811660a052811660c05262000078620000ac565b505050620001d4565b6001600160a01b038116620000a9576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff1615620001195760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016b576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018557600080fd5b919050565b600080600060608486031215620001a057600080fd5b620001ab846200016d565b9250620001bb602085016200016d565b9150620001cb604085016200016d565b90509250925092565b60805160a05160c05161589f62000227600039600081816103e20152612d310152600081816103bb0152612c6e0152600081816106c501528181610d7a01528181612bb501526134a6015261589f6000f3fe608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614df0565b6106f0565b005b61037b610376366004614e0d565b610704565b60408051928352602083019190915201610315565b61036661039e366004614df0565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e4f565b6107d0565b610343610425366004614eae565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614df0565b61091a565b610366610467366004614df0565b61092b565b61036661047a366004614f33565b61093c565b61036661048d366004614fcd565b610973565b610366610b4a565b6104ad6104a8366004614df0565b610c30565b60405161031591906150ba565b61037b6104c8366004614e0d565b610dcc565b6103666104db366004615107565b610eb1565b61037b6104ee366004614e0d565b610f58565b61037b610501366004614e0d565b611061565b610519610514366004614eae565b611160565b604051908152602001610315565b610519610535366004614df0565b6001600160a01b0316600090815261012d602052604090205490565b610366611225565b610366610567366004615148565b611239565b610366611280565b610366610582366004614df0565b61130b565b6033546001600160a01b0316610301565b61037b6105a6366004614e4f565b611392565b6103666105b9366004614eae565b611488565b61012f54610301906001600160a01b031681565b6106076105e0366004614eae565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516103159291906151cb565b6097546001600160a01b0316610301565b61037b610634366004614e4f565b6114be565b6103666115b4565b61036661064f3660046151df565b611666565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e4f565b611704565b6103666106a836600461528f565b611833565b6103666106bb366004614df0565b611bdc565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c65565b61070181611cbf565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615161565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d3c565b508092505050935093915050565b6107c7611c65565b610701816120a2565b6000808285856107de612197565b6107e7836121ec565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61085761222c565b6108648a8a8a8a8a612285565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae88888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c65565b61070181612680565b610933611c65565b610701816126fd565b61095d6040518060600160405280603c815260200161582e603c913961277a565b61096b868686868686612846565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612b17565b610a97896121ec565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad9878787878787612846565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e2829000000000000000000000000000081525061277a565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153f8565b9050610cc882612bb0565b15610dc75780516000610cdc82600161545c565b67ffffffffffffffff811115610cf457610cf4615300565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615474565b6020026020010151828281518110610d5757610d57615474565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615474565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615161565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d7c565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ea757610ea1610e9b670de0b6b3a7640000836154a3565b83613089565b93508092505b5050935093915050565b610eb9611c65565b610ec161222c565b610eca836121ec565b610ed3826121ec565b610edc816130b5565b82610ee781836130ef565b610efb6001600160a01b03821684846133f9565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f4091815260200190565b60405180910390a350610f53600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fbc57600080fd5b505af1158015610fd0573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561103457600080fd5b505af1158015611048573d6000803e3d6000fd5b50505050611057858585612d7c565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110c557600080fd5b505af11580156110d9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561113d57600080fd5b505af1158015611151573d6000803e3d6000fd5b50505050611057858585611d3c565b600061116e60c95460021490565b156111a5576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111af83836134a2565b6111f8576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b61122d611c65565b6112376000613590565b565b6112776040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e7432353629000081525061277a565b610701816135c1565b60655433906001600160a01b031681146113025760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613590565b611313611c65565b61131c816121ec565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113a0612197565b6113a9836121ec565b816001600160a01b0316836001600160a01b031614806113da5750806001600160a01b0316836001600160a01b0316145b15611411576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61141961222c565b6114268a8a8a8a8a612285565b909550935061143788888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b61149061222c565b600061149c838361360b565b905080156114af576114af838383613968565b506114ba600160c955565b5050565b6000808285856114cc612197565b6114d5836121ec565b816001600160a01b0316836001600160a01b031614806115065750806001600160a01b0316836001600160a01b0316145b1561153d576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61154561222c565b6115528a8a8a8a8a613e04565b909550935061156388888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b6115f26040518060400160405280601181526020017f7061757365436f6e76657273696f6e282900000000000000000000000000000081525061277a565b6115fa612197565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116a0576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156116fb576116f3878787848181106116c1576116c1615474565b90506020020160208101906116d69190614df0565b8686858181106116e8576116e8615474565b905060400201611833565b6001016116a3565b50505050505050565b600080828585611712612197565b61171b836121ec565b816001600160a01b0316836001600160a01b0316148061174c5750806001600160a01b0316836001600160a01b0316145b15611783576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61178b61222c565b6117988a8a8a8a8a613e96565b90955093508884146117d6576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117e288888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b6118546040518060600160405280603581526020016157f96035913961277a565b61185d836121ec565b611866826121ec565b6706f05b59d3b20000813511156118ba576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b031614806118f357506118dd613f53565b6001600160a01b0316836001600160a01b031614155b8061193b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561193857611938615161565b14155b15611972576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261198460408301602084016154e0565b600381111561199557611995615161565b1480156119a25750803515155b156119d9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026119eb60408301602084016154e0565b60038111156119fc576119fc615161565b1480611a2857506001611a1560408301602084016154e0565b6003811115611a2657611a26615161565b145b8015611a3d575060ff546001600160a01b0316155b15611a74576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611ae491908a01908a016154e0565b604051611af49493929190615501565b60405180910390a36000611b0e60408401602085016154e0565b6003811115611b1f57611b1f615161565b03611b7c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bd6565b81358155611b9060408301602084016154e0565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611bd057611bd0615161565b02179055505b50505050565b611be4611c65565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c2d6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611cc8816121ec565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d79576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611dcd57611dcd615161565b6003811115611dde57611dde615161565b9052509050600081602001516003811115611dfb57611dfb615161565b03611e32576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611e96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eba9190615532565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f479190615532565b835160ff54919250906000906001600160a01b031615801590611fea575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fea919061554b565b90508015611ff757600091505b600061200b83670de0b6b3a764000061545c565b9050811561204b5761201d81866154a3565b670de0b6b3a7640000612030868e6154a3565b61203a91906154a3565b612044919061556d565b975061207d565b61207a670de0b6b3a7640000612061868e6154a3565b61206b91906154a3565b61207583886154a3565b613089565b97505b8361208882876154a3565b612092919061556d565b9650505050505050935093915050565b6001600160a01b03811661211e5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611237576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c9540361227e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b6000806122928585613fdf565b61229c85886140ff565b91506122a9828686610f58565b915050858110156122f0576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b6122fb84848361424a565b9550959350505050565b600061231084610c30565b6001600160a01b038516600090815261012d60205260408120549192509061233990849061545c565b9050612344816130b5565b815160008080805b8481101561266c57600061012e600089848151811061236d5761236d615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b0316815260200190815260200160002054905080600014612663576123ce6001876155a8565b82101561242e576123fa8883815181106123ea576123ea615474565b60200260200101518c8b8a6142c4565b612404908661545c565b945086612411828c6154a3565b61241b919061556d565b9350612427848461545c565b9250612529565b600061243a868b6155a8565b90508061012e60008b868151811061245457612454615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546124ae91906155a8565b925050819055508b6001600160a01b03168984815181106124d1576124d1615474565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161251391815260200190565b60405180910390a3612525848c6155a8565b9450505b8b6001600160a01b031688838151811061254557612545615474565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af55876040516125a691815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125d7576125d7615474565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561264a57600080fd5b505af115801561265e573d6000803e3d6000fd5b505050505b5060010161234c565b5050505050505050505050565b600160c955565b612689816121ec565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b612706816121ec565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906127c69033908690600401615617565b602060405180830381865afa1580156127e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612807919061554b565b9050806114ba573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b93929190615639565b8483811415806128565750808214155b1561288d576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b0d5760008686838181106128ac576128ac615474565b90506020028101906128be9190615665565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945088925087915085905081811061290657612906615474565b90506020028101906129189190615665565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505084518351939450928314915061298b9050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612afe578281815181106129a8576129a8615474565b602002602001015161013060008e8e898181106129c7576129c7615474565b90506020020160208101906129dc9190614df0565b6001600160a01b03166001600160a01b031681526020019081526020016000206000868481518110612a1057612a10615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a6157612a61615474565b60200260200101516001600160a01b03168c8c87818110612a8457612a84615474565b9050602002016020810190612a999190614df0565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612ad557612ad5615474565b6020026020010151604051612aee911515815260200190565b60405180910390a360010161298e565b50836001019350505050612890565b5050505050505050565b600054610100900460ff16612b945760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612b9d8461439d565b612ba561442b565b611bd68383836144b0565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612c11573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c3991908101906153f8565b805190915060005b81811015612d7457828181518110612c5b57612c5b615474565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d2f57846001600160a01b0316838281518110612cb757612cb7615474565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d2091906156cd565b6001600160a01b031614612d65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d7457600101612c41565b505050919050565b60008084600003612db9576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612e0d57612e0d615161565b6003811115612e1e57612e1e615161565b9052509050600081602001516003811115612e3b57612e3b615161565b03612e72576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ed6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efa9190615532565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f879190615532565b835160ff54919250906001600160a01b031615801590613027575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015613003573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613027919061554b565b15613030575060005b600061304482670de0b6b3a764000061545c565b90508261305182866154a3565b61305b919061556d565b9550670de0b6b3a7640000613070878c6154a3565b61307a919061556d565b96505050505050935093915050565b6000816001613098828661545c565b6130a291906155a8565b6130ac919061556d565b90505b92915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561314f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131739190615532565b9050808211156131af576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d60205260408120546131d390836155a8565b905082811015611bd65780830360006131eb86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b828110156133bf5761012e600086838151811061322d5761322d615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133b75761328b6001846155a8565b8110156132c8576132b78582815181106132a7576132a7615474565b60200260200101518b88876142c4565b6132c1908361545c565b91506133b7565b60006132d483886155a8565b90508061012e60008885815181106132ee576132ee615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461334891906155a8565b925050819055508a6001600160a01b031686838151811061336b5761336b615474565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce38836040516133ad91815260200190565b60405180910390a3505b60010161320e565b506001600160a01b038916600090815261012d6020526040812080548792906133e99084906155a8565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f539084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614575565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134ed576134e682612bb0565b90506130af565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa15801561355a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357e91906156cd565b6001600160a01b031614159392505050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556107018161465d565b6135ca816130b5565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b600061361783836134a2565b613660576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156136c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e69190615532565b6001600160a01b038516600090815261012d60205260409020549091508082111561395f576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff161561395f5760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa1580156137a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c89190615532565b60fe549091506137e5906001600160a01b038681169116876133f9565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561384a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061386e9190615532565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac353789896138d986866155a8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561394057600080fd5b505af1158015613954573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613972613f53565b60fe5460ff549192506001600160a01b03908116916000911615613df75760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af1158015613a01573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a2991908101906156ea565b8151919350915060005b81811015613df257828181518110613a4d57613a4d615474565b602002602001015160000315613df2576000848281518110613a7157613a71615474565b60200260200101516001600160a01b0316636f1a30a8858481518110613a9957613a99615474565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613adb939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613af9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1d91906157a5565b91505088811115613b2b5750875b613b35818b6146c7565b613b3f5750613df2565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613ba2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bc69190615532565b90508a6001600160a01b031663095ea7b3878581518110613be957613be9615474565b6020026020010151846040518363ffffffff1660e01b8152600401613c239291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c66919061554b565b50858381518110613c7957613c79615474565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613d03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2791906157a5565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613db09190615532565b9050613dbc838c6155a8565b9a50613dc882826155a8565b613dd2908961545c565b97508a600003613de457505050613df2565b836001019350505050613a33565b505050505b61096b86848388886147ff565b600080613e118585613fdf565b6000613e1e878787611061565b91505087811115613e65576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e6f86826140ff565b9250613e7c838787610f58565b9250613e8b905085858461424a565b509550959350505050565b600080613ea38585613fdf565b6000613eb0878787611061565b915050613ebd86826140ff565b9250808314613ef8576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613f3c576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f4785858961424a565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fda91906156cd565b905090565b60ff546000906001600160a01b03161580159061407c575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015614058573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061407c919061554b565b9050801580156140c8575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff1660038111156140c6576140c6615161565b145b15610f53576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015614168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418c9190615532565b60fe549091506141ab906001600160a01b03848116913391168761499d565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015614210573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142349190615532565b905061424082826155a8565b9695505050505050565b6001600160a01b038316600090815261012d60205260409020548181101561429e576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142a884836149ee565b836142bd6001600160a01b03821685856133f9565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142fa9085906154a3565b614304919061556d565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143419084906155a8565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161438d91815260200190565b60405180910390a3949350505050565b600054610100900460ff1661441a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614422614a20565b61070181614aa5565b600054610100900460ff166144a85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611237614b22565b600054610100900460ff1661452d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614536836126fd565b61453f82611cbf565b614548816135c1565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b60006145ca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b9f9092919063ffffffff16565b90508051600014806145eb5750808060200190518101906145eb919061554b565b610f535760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561472857600080fd5b505af115801561473c573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156147b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147d49190615532565b6147de91906154a3565b6147e8919061556d565b905060fb5481106147f857600191505b5092915050565b82156148d65760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b1580156148bd57600080fd5b505af11580156148d1573d6000803e3d6000fd5b505050505b80156142bd576001600160a01b038216600090815261012d60205260408120805483929061490590849061545c565b90915550506001600160a01b03808616600090815261012e602090815260408083209386168352929052908120805483929061494290849061545c565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161498e91815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bd69085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161343e565b6001600160a01b038216600090815261012d602052604081208054839290614a179084906155a8565b90915550505050565b600054610100900460ff16614a9d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611237614bb8565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126795760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614bae8484600085614c3e565b90505b9392505050565b600054610100900460ff16614c355760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61123733613590565b606082471015614cb65760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614cd291906157c9565b60006040518083038185875af1925050503d8060008114614d0f576040519150601f19603f3d011682016040523d82523d6000602084013e614d14565b606091505b5091509150614d2587838387614d32565b925050505b949350505050565b60608315614da1578251600003614d9a576001600160a01b0385163b614d9a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614d2a565b614d2a8383815115614db65781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157e5565b6001600160a01b038116811461070157600080fd5b8035610dc781614dd0565b600060208284031215614e0257600080fd5b8135614bb181614dd0565b600080600060608486031215614e2257600080fd5b833592506020840135614e3481614dd0565b91506040840135614e4481614dd0565b809150509250925092565b600080600080600060a08688031215614e6757600080fd5b85359450602086013593506040860135614e8081614dd0565b92506060860135614e9081614dd0565b91506080860135614ea081614dd0565b809150509295509295909350565b60008060408385031215614ec157600080fd5b8235614ecc81614dd0565b91506020830135614edc81614dd0565b809150509250929050565b60008083601f840112614ef957600080fd5b50813567ffffffffffffffff811115614f1157600080fd5b6020830191508360208260051b8501011115614f2c57600080fd5b9250929050565b60008060008060008060608789031215614f4c57600080fd5b863567ffffffffffffffff80821115614f6457600080fd5b614f708a838b01614ee7565b90985096506020890135915080821115614f8957600080fd5b614f958a838b01614ee7565b90965094506040890135915080821115614fae57600080fd5b50614fbb89828a01614ee7565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fef57600080fd5b614ff88c614de5565b9a5061500660208d01614de5565b995061501460408d01614de5565b985061502260608d01614de5565b975060808c0135965067ffffffffffffffff8060a08e0135111561504557600080fd5b6150558e60a08f01358f01614ee7565b909750955060c08d013581101561506b57600080fd5b61507b8e60c08f01358f01614ee7565b909550935060e08d013581101561509157600080fd5b506150a28d60e08e01358e01614ee7565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150fb5783516001600160a01b0316835292840192918401916001016150d6565b50909695505050505050565b60008060006060848603121561511c57600080fd5b833561512781614dd0565b9250602084013561513781614dd0565b929592945050506040919091013590565b60006020828403121561515a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106151c7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614bb16020830184615190565b6000806000806000606086880312156151f757600080fd5b853561520281614dd0565b9450602086013567ffffffffffffffff8082111561521f57600080fd5b61522b89838a01614ee7565b9096509450604088013591508082111561524457600080fd5b818801915088601f83011261525857600080fd5b81358181111561526757600080fd5b8960208260061b850101111561527c57600080fd5b9699959850939650602001949392505050565b600080600083850360808112156152a557600080fd5b84356152b081614dd0565b935060208501356152c081614dd0565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152f257600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561535857615358615300565b604052919050565b600067ffffffffffffffff82111561537a5761537a615300565b5060051b60200190565b600082601f83011261539557600080fd5b815160206153aa6153a583615360565b61532f565b82815260059290921b840181019181810190868411156153c957600080fd5b8286015b848110156153ed5780516153e081614dd0565b83529183019183016153cd565b509695505050505050565b60006020828403121561540a57600080fd5b815167ffffffffffffffff81111561542157600080fd5b614d2a84828501615384565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561546f5761546f61542d565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156154db576154db61542d565b500290565b6000602082840312156154f257600080fd5b813560048110614bb157600080fd5b848152602081018490526080810161551c6040830185615190565b6155296060830184615190565b95945050505050565b60006020828403121561554457600080fd5b5051919050565b60006020828403121561555d57600080fd5b81518015158114614bb157600080fd5b6000826155a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000828210156155ba576155ba61542d565b500390565b60005b838110156155da5781810151838201526020016155c2565b83811115611bd65750506000910152565b600081518084526156038160208601602086016155bf565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614bae60408301846155eb565b60006001600160a01b0380861683528085166020840152506060604083015261552960608301846155eb565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261569a57600080fd5b83018035915067ffffffffffffffff8211156156b557600080fd5b6020019150600581901b3603821315614f2c57600080fd5b6000602082840312156156df57600080fd5b8151614bb181614dd0565b600080604083850312156156fd57600080fd5b825167ffffffffffffffff8082111561571557600080fd5b61572186838701615384565b935060209150818501518181111561573857600080fd5b85019050601f8101861361574b57600080fd5b80516157596153a582615360565b81815260059190911b8201830190838101908883111561577857600080fd5b928401925b828410156157965783518252928401929084019061577d565b80955050505050509250929050565b600080604083850312156157b857600080fd5b505080516020909101519092909150565b600082516157db8184602087016155bf565b9190910192915050565b6020815260006130ac60208301846155eb56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a26469706673582212205f6f2758e0a194168e1ee21858c7de5575e3041602ba60b90cda24613fdac4b864736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102e95760003560e01c806370a0823111610191578063b6828c57116100e3578063e30c397811610097578063f2fde38b11610071578063f2fde38b146106ad578063fa7b81a0146106c0578063fe3da984146106e757600080fd5b8063e30c397814610676578063f04c318714610687578063f0dc7e9d1461069a57600080fd5b8063c0654646116100c8578063c065464614610641578063ca32546914610654578063e2ff7ea21461066757600080fd5b8063b6828c5714610626578063bc368b041461063957600080fd5b80638da5cb5b11610145578063afcff50f1161011f578063afcff50f146105be578063b491ddf7146105d2578063b4a0bdf31461061557600080fd5b80638da5cb5b1461058757806390fa7b5414610598578063aac59a75146105ab57600080fd5b8063746460a911610176578063746460a91461055957806379ba50971461056c5780637b77cd6a1461057457600080fd5b806370a0823114610527578063715018a61461055157600080fd5b806352e21a181161024a5780635c39f467116101fe5780636daa463b116101d85780636daa463b146104e05780636f1a30a8146104f35780636fb052751461050657600080fd5b80635c39f4671461049a5780635e1e6325146104ba57806364aff9ec146104cd57600080fd5b8063553745221161022f578063553745221461046c578063556bbd8a1461047f57806358b904df1461049257600080fd5b806352e21a1814610446578063530e784f1461045957600080fd5b80632630c12f116102a1578063362b679511610286578063362b6795146103dd578063439727a514610404578063454900fe1461041757600080fd5b80632630c12f146103a35780633421fc52146103b657600080fd5b80630a0a05e6116102d25780630a0a05e6146103535780630a9a2b72146103685780630e32cb861461039057600080fd5b806301e20178146102ee57806307aa239e1461031e575b600080fd5b60ff54610301906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546103439074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610315565b610366610361366004614df0565b6106f0565b005b61037b610376366004614e0d565b610704565b60408051928352602083019190915201610315565b61036661039e366004614df0565b6107bf565b60fc54610301906001600160a01b031681565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61037b610412366004614e4f565b6107d0565b610343610425366004614eae565b61013060209081526000928352604080842090915290825290205460ff1681565b610366610454366004614df0565b61091a565b610366610467366004614df0565b61092b565b61036661047a366004614f33565b61093c565b61036661048d366004614fcd565b610973565b610366610b4a565b6104ad6104a8366004614df0565b610c30565b60405161031591906150ba565b61037b6104c8366004614e0d565b610dcc565b6103666104db366004615107565b610eb1565b61037b6104ee366004614e0d565b610f58565b61037b610501366004614e0d565b611061565b610519610514366004614eae565b611160565b604051908152602001610315565b610519610535366004614df0565b6001600160a01b0316600090815261012d602052604090205490565b610366611225565b610366610567366004615148565b611239565b610366611280565b610366610582366004614df0565b61130b565b6033546001600160a01b0316610301565b61037b6105a6366004614e4f565b611392565b6103666105b9366004614eae565b611488565b61012f54610301906001600160a01b031681565b6106076105e0366004614eae565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516103159291906151cb565b6097546001600160a01b0316610301565b61037b610634366004614e4f565b6114be565b6103666115b4565b61036661064f3660046151df565b611666565b60fe54610301906001600160a01b031681565b6105196706f05b59d3b2000081565b6065546001600160a01b0316610301565b61037b610695366004614e4f565b611704565b6103666106a836600461528f565b611833565b6103666106bb366004614df0565b611bdc565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b61051960fb5481565b6106f8611c65565b61070181611cbf565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff16600381111561074657610746615161565b0361077d576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d6020526040902054858110156107a3578095505b8592506107b1868686611d3c565b508092505050935093915050565b6107c7611c65565b610701816120a2565b6000808285856107de612197565b6107e7836121ec565b816001600160a01b0316836001600160a01b031614806108185750806001600160a01b0316836001600160a01b0316145b1561084f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61085761222c565b6108648a8a8a8a8a612285565b90955093508985146108a2576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae88888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a461090d600160c955565b5050509550959350505050565b610922611c65565b61070181612680565b610933611c65565b610701816126fd565b61095d6040518060600160405280603c815260200161582e603c913961277a565b61096b868686868686612846565b505050505050565b600054610100900460ff16158080156109935750600054600160ff909116105b806109ad5750303b1580156109ad575060005460ff166001145b610a245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a8e8c8c8c8b612b17565b610a97896121ec565b61012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b16179055610ad9878787878787612846565b8015610b3c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b610b886040518060400160405280601281526020017f726573756d65436f6e76657273696f6e2829000000000000000000000000000081525061277a565b60fe5474010000000000000000000000000000000000000000900460ff16610bdb576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b61012f546040517ff36dba380000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152606092169063f36dba3890602401600060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbd91908101906153f8565b9050610cc882612bb0565b15610dc75780516000610cdc82600161545c565b67ffffffffffffffff811115610cf457610cf4615300565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b50905060005b82811015610d7757838181518110610d3d57610d3d615474565b6020026020010151828281518110610d5757610d57615474565b6001600160a01b0390921660209283029190910190910152600101610d23565b507f0000000000000000000000000000000000000000000000000000000000000000818381518110610dab57610dab615474565b6001600160a01b03909216602092830291909101909101529150505b919050565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff166003811115610e0e57610e0e615161565b03610e45576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610e55868686612d7c565b90925090506000610e7c856001600160a01b0316600090815261012d602052604090205490565b905082811015610ea757610ea1610e9b670de0b6b3a7640000836154a3565b83613089565b93508092505b5050935093915050565b610eb9611c65565b610ec161222c565b610eca836121ec565b610ed3826121ec565b610edc816130b5565b82610ee781836130ef565b610efb6001600160a01b03821684846133f9565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d584604051610f4091815260200190565b60405180910390a350610f53600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610fbc57600080fd5b505af1158015610fd0573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561103457600080fd5b505af1158015611048573d6000803e3d6000fd5b50505050611057858585612d7c565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b1580156110c557600080fd5b505af11580156110d9573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b15801561113d57600080fd5b505af1158015611151573d6000803e3d6000fd5b50505050611057858585611d3c565b600061116e60c95460021490565b156111a5576040517f9a050fe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111af83836134a2565b6111f8576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b506001600160a01b03918216600090815261012e6020908152604080832093909416825291909152205490565b61122d611c65565b6112376000613590565b565b6112776040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e7432353629000081525061277a565b610701816135c1565b60655433906001600160a01b031681146113025760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a1b565b61070181613590565b611313611c65565b61131c816121ec565b61012f546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000808285856113a0612197565b6113a9836121ec565b816001600160a01b0316836001600160a01b031614806113da5750806001600160a01b0316836001600160a01b0316145b15611411576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61141961222c565b6114268a8a8a8a8a612285565b909550935061143788888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb77154906060016108fb565b61149061222c565b600061149c838361360b565b905080156114af576114af838383613968565b506114ba600160c955565b5050565b6000808285856114cc612197565b6114d5836121ec565b816001600160a01b0316836001600160a01b031614806115065750806001600160a01b0316836001600160a01b0316145b1561153d576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61154561222c565b6115528a8a8a8a8a613e04565b909550935061156388888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e82906060016108fb565b6115f26040518060400160405280601181526020017f7061757365436f6e76657273696f6e282900000000000000000000000000000081525061277a565b6115fa612197565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b828181146116a0576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156116fb576116f3878787848181106116c1576116c1615474565b90506020020160208101906116d69190614df0565b8686858181106116e8576116e8615474565b905060400201611833565b6001016116a3565b50505050505050565b600080828585611712612197565b61171b836121ec565b816001600160a01b0316836001600160a01b0316148061174c5750806001600160a01b0316836001600160a01b0316145b15611783576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61178b61222c565b6117988a8a8a8a8a613e96565b90955093508884146117d6576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117e288888787612305565b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe076906060016108fb565b6118546040518060600160405280603581526020016157f96035913961277a565b61185d836121ec565b611866826121ec565b6706f05b59d3b20000813511156118ba576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610a1b565b816001600160a01b0316836001600160a01b031614806118f357506118dd613f53565b6001600160a01b0316836001600160a01b031614155b8061193b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561193857611938615161565b14155b15611972576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261198460408301602084016154e0565b600381111561199557611995615161565b1480156119a25750803515155b156119d9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026119eb60408301602084016154e0565b60038111156119fc576119fc615161565b1480611a2857506001611a1560408301602084016154e0565b6003811115611a2657611a26615161565b145b8015611a3d575060ff546001600160a01b0316155b15611a74576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff90911691611ae491908a01908a016154e0565b604051611af49493929190615501565b60405180910390a36000611b0e60408401602085016154e0565b6003811115611b1f57611b1f615161565b03611b7c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611bd6565b81358155611b9060408301602084016154e0565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115611bd057611bd0615161565b02179055505b50505050565b611be4611c65565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611c2d6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146112375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a1b565b611cc8816121ec565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60008084600003611d79576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115611dcd57611dcd615161565b6003811115611dde57611dde615161565b9052509050600081602001516003811115611dfb57611dfb615161565b03611e32576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015611e96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eba9190615532565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f479190615532565b835160ff54919250906000906001600160a01b031615801590611fea575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611fc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fea919061554b565b90508015611ff757600091505b600061200b83670de0b6b3a764000061545c565b9050811561204b5761201d81866154a3565b670de0b6b3a7640000612030868e6154a3565b61203a91906154a3565b612044919061556d565b975061207d565b61207a670de0b6b3a7640000612061868e6154a3565b61206b91906154a3565b61207583886154a3565b613089565b97505b8361208882876154a3565b612092919061556d565b9650505050505050935093915050565b6001600160a01b03811661211e5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610a1b565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b60fe5474010000000000000000000000000000000000000000900460ff1615611237576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610701576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c9540361227e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a1b565b600260c955565b6000806122928585613fdf565b61229c85886140ff565b91506122a9828686610f58565b915050858110156122f0576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610a1b565b6122fb84848361424a565b9550959350505050565b600061231084610c30565b6001600160a01b038516600090815261012d60205260408120549192509061233990849061545c565b9050612344816130b5565b815160008080805b8481101561266c57600061012e600089848151811061236d5761236d615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b0316815260200190815260200160002054905080600014612663576123ce6001876155a8565b82101561242e576123fa8883815181106123ea576123ea615474565b60200260200101518c8b8a6142c4565b612404908661545c565b945086612411828c6154a3565b61241b919061556d565b9350612427848461545c565b9250612529565b600061243a868b6155a8565b90508061012e60008b868151811061245457612454615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546124ae91906155a8565b925050819055508b6001600160a01b03168984815181106124d1576124d1615474565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161251391815260200190565b60405180910390a3612525848c6155a8565b9450505b8b6001600160a01b031688838151811061254557612545615474565b60200260200101516001600160a01b031660fe60009054906101000a90046001600160a01b03166001600160a01b03167fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af55876040516125a691815260200190565b60405180910390a460fe5488516001600160a01b03909116906353ac3537908a90859081106125d7576125d7615474565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039182166004820152908f16602482015260448101879052606401600060405180830381600087803b15801561264a57600080fd5b505af115801561265e573d6000803e3d6000fd5b505050505b5060010161234c565b5050505050505050505050565b600160c955565b612689816121ec565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b612706816121ec565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906127c69033908690600401615617565b602060405180830381865afa1580156127e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612807919061554b565b9050806114ba573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610a1b93929190615639565b8483811415806128565750808214155b1561288d576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612b0d5760008686838181106128ac576128ac615474565b90506020028101906128be9190615665565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945088925087915085905081811061290657612906615474565b90506020028101906129189190615665565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505084518351939450928314915061298b9050576040517f5f6f132c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015612afe578281815181106129a8576129a8615474565b602002602001015161013060008e8e898181106129c7576129c7615474565b90506020020160208101906129dc9190614df0565b6001600160a01b03166001600160a01b031681526020019081526020016000206000868481518110612a1057612a10615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550838181518110612a6157612a61615474565b60200260200101516001600160a01b03168c8c87818110612a8457612a84615474565b9050602002016020810190612a999190614df0565b6001600160a01b03167f6333c55c3657aafc9b39e2586076d198ed0250804559126489c852f28d51280c858481518110612ad557612ad5615474565b6020026020010151604051612aee911515815260200190565b60405180910390a360010161298e565b50836001019350505050612890565b5050505050505050565b600054610100900460ff16612b945760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b612b9d8461439d565b612ba561442b565b611bd68383836144b0565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612c11573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c3991908101906153f8565b805190915060005b81811015612d7457828181518110612c5b57612c5b615474565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612d2f57846001600160a01b0316838281518110612cb757612cb7615474565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d2091906156cd565b6001600160a01b031614612d65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b935083612d7457600101612c41565b505050919050565b60008084600003612db9576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff166003811115612e0d57612e0d615161565b6003811115612e1e57612e1e615161565b9052509050600081602001516003811115612e3b57612e3b615161565b03612e72576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa158015612ed6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efa9190615532565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612f63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f879190615532565b835160ff54919250906001600160a01b031615801590613027575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015613003573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613027919061554b565b15613030575060005b600061304482670de0b6b3a764000061545c565b90508261305182866154a3565b61305b919061556d565b9550670de0b6b3a7640000613070878c6154a3565b61307a919061556d565b96505050505050935093915050565b6000816001613098828661545c565b6130a291906155a8565b6130ac919061556d565b90505b92915050565b80600003610701576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561314f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131739190615532565b9050808211156131af576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815261012d60205260408120546131d390836155a8565b905082811015611bd65780830360006131eb86610c30565b6001600160a01b038716600090815261012d602052604081205482519293509190805b828110156133bf5761012e600086838151811061322d5761322d615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020546000146133b75761328b6001846155a8565b8110156132c8576132b78582815181106132a7576132a7615474565b60200260200101518b88876142c4565b6132c1908361545c565b91506133b7565b60006132d483886155a8565b90508061012e60008885815181106132ee576132ee615474565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461334891906155a8565b925050819055508a6001600160a01b031686838151811061336b5761336b615474565b60200260200101516001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce38836040516133ad91815260200190565b60405180910390a3505b60010161320e565b506001600160a01b038916600090815261012d6020526040812080548792906133e99084906155a8565b9091555050505050505050505050565b6040516001600160a01b038316602482015260448101829052610f539084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614575565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036134ed576134e682612bb0565b90506130af565b61012f546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa15801561355a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357e91906156cd565b6001600160a01b031614159392505050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556107018161465d565b6135ca816130b5565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b600061361783836134a2565b613660576040517f983f1fb50000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015283166024820152604401610a1b565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156136c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e69190615532565b6001600160a01b038516600090815261012d60205260409020549091508082111561395f576001600160a01b0380871660009081526101306020908152604080832093891683529290522054818303945060ff161561395f5760fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918516906370a0823190602401602060405180830381865afa1580156137a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c89190615532565b60fe549091506137e5906001600160a01b038681169116876133f9565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918616906370a0823190602401602060405180830381865afa15801561384a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061386e9190615532565b60fe546040518881529192506001600160a01b03898116928b82169291909116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546001600160a01b03166353ac353789896138d986866155a8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561394057600080fd5b505af1158015613954573d6000803e3d6000fd5b505050506000955050505b50505092915050565b6000613972613f53565b60fe5460ff549192506001600160a01b03908116916000911615613df75760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af1158015613a01573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a2991908101906156ea565b8151919350915060005b81811015613df257828181518110613a4d57613a4d615474565b602002602001015160000315613df2576000848281518110613a7157613a71615474565b60200260200101516001600160a01b0316636f1a30a8858481518110613a9957613a99615474565b60200260200101518c8b6040518463ffffffff1660e01b8152600401613adb939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af1158015613af9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1d91906157a5565b91505088811115613b2b5750875b613b35818b6146c7565b613b3f5750613df2565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa158015613ba2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bc69190615532565b90508a6001600160a01b031663095ea7b3878581518110613be957613be9615474565b6020026020010151846040518363ffffffff1660e01b8152600401613c239291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c66919061554b565b50858381518110613c7957613c79615474565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015613d03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2791906157a5565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015613d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613db09190615532565b9050613dbc838c6155a8565b9a50613dc882826155a8565b613dd2908961545c565b97508a600003613de457505050613df2565b836001019350505050613a33565b505050505b61096b86848388886147ff565b600080613e118585613fdf565b6000613e1e878787611061565b91505087811115613e65576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613e6f86826140ff565b9250613e7c838787610f58565b9250613e8b905085858461424a565b509550959350505050565b600080613ea38585613fdf565b6000613eb0878787611061565b915050613ebd86826140ff565b9250808314613ef8576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115613f3c576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610a1b565b613f4785858961424a565b50909694955050505050565b60fe54604080517fc8ecc0d300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c8ecc0d39160048083019260209291908290030181865afa158015613fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fda91906156cd565b905090565b60ff546000906001600160a01b03161580159061407c575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015614058573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061407c919061554b565b9050801580156140c8575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff1660038111156140c6576140c6615161565b145b15610f53576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015614168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418c9190615532565b60fe549091506141ab906001600160a01b03848116913391168761499d565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015614210573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142349190615532565b905061424082826155a8565b9695505050505050565b6001600160a01b038316600090815261012d60205260409020548181101561429e576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142a884836149ee565b836142bd6001600160a01b03821685856133f9565b5050505050565b6001600160a01b03808516600090815261012e6020908152604080832093871683529290529081205482906142fa9085906154a3565b614304919061556d565b6001600160a01b03808716600090815261012e602090815260408083209389168352929052908120805492935083929091906143419084906155a8565b92505081905550836001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161438d91815260200190565b60405180910390a3949350505050565b600054610100900460ff1661441a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614422614a20565b61070181614aa5565b600054610100900460ff166144a85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611237614b22565b600054610100900460ff1661452d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b614536836126fd565b61453f82611cbf565b614548816135c1565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b60006145ca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b9f9092919063ffffffff16565b90508051600014806145eb5750808060200190518101906145eb919061554b565b610f535760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a1b565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561472857600080fd5b505af115801561473c573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156147b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147d49190615532565b6147de91906154a3565b6147e8919061556d565b905060fb5481106147f857600191505b5092915050565b82156148d65760fe546040518481526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a460fe546040517f53ac35370000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152868116602483015260448201869052909116906353ac353790606401600060405180830381600087803b1580156148bd57600080fd5b505af11580156148d1573d6000803e3d6000fd5b505050505b80156142bd576001600160a01b038216600090815261012d60205260408120805483929061490590849061545c565b90915550506001600160a01b03808616600090815261012e602090815260408083209386168352929052908120805483929061494290849061545c565b92505081905550816001600160a01b0316856001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161498e91815260200190565b60405180910390a35050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611bd69085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161343e565b6001600160a01b038216600090815261012d602052604081208054839290614a179084906155a8565b90915550505050565b600054610100900460ff16614a9d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b611237614bb8565b600054610100900460ff166107c75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b600054610100900460ff166126795760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b6060614bae8484600085614c3e565b90505b9392505050565b600054610100900460ff16614c355760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a1b565b61123733613590565b606082471015614cb65760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a1b565b600080866001600160a01b03168587604051614cd291906157c9565b60006040518083038185875af1925050503d8060008114614d0f576040519150601f19603f3d011682016040523d82523d6000602084013e614d14565b606091505b5091509150614d2587838387614d32565b925050505b949350505050565b60608315614da1578251600003614d9a576001600160a01b0385163b614d9a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a1b565b5081614d2a565b614d2a8383815115614db65781518083602001fd5b8060405162461bcd60e51b8152600401610a1b91906157e5565b6001600160a01b038116811461070157600080fd5b8035610dc781614dd0565b600060208284031215614e0257600080fd5b8135614bb181614dd0565b600080600060608486031215614e2257600080fd5b833592506020840135614e3481614dd0565b91506040840135614e4481614dd0565b809150509250925092565b600080600080600060a08688031215614e6757600080fd5b85359450602086013593506040860135614e8081614dd0565b92506060860135614e9081614dd0565b91506080860135614ea081614dd0565b809150509295509295909350565b60008060408385031215614ec157600080fd5b8235614ecc81614dd0565b91506020830135614edc81614dd0565b809150509250929050565b60008083601f840112614ef957600080fd5b50813567ffffffffffffffff811115614f1157600080fd5b6020830191508360208260051b8501011115614f2c57600080fd5b9250929050565b60008060008060008060608789031215614f4c57600080fd5b863567ffffffffffffffff80821115614f6457600080fd5b614f708a838b01614ee7565b90985096506020890135915080821115614f8957600080fd5b614f958a838b01614ee7565b90965094506040890135915080821115614fae57600080fd5b50614fbb89828a01614ee7565b979a9699509497509295939492505050565b60008060008060008060008060008060006101008c8e031215614fef57600080fd5b614ff88c614de5565b9a5061500660208d01614de5565b995061501460408d01614de5565b985061502260608d01614de5565b975060808c0135965067ffffffffffffffff8060a08e0135111561504557600080fd5b6150558e60a08f01358f01614ee7565b909750955060c08d013581101561506b57600080fd5b61507b8e60c08f01358f01614ee7565b909550935060e08d013581101561509157600080fd5b506150a28d60e08e01358e01614ee7565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b818110156150fb5783516001600160a01b0316835292840192918401916001016150d6565b50909695505050505050565b60008060006060848603121561511c57600080fd5b833561512781614dd0565b9250602084013561513781614dd0565b929592945050506040919091013590565b60006020828403121561515a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106151c7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101614bb16020830184615190565b6000806000806000606086880312156151f757600080fd5b853561520281614dd0565b9450602086013567ffffffffffffffff8082111561521f57600080fd5b61522b89838a01614ee7565b9096509450604088013591508082111561524457600080fd5b818801915088601f83011261525857600080fd5b81358181111561526757600080fd5b8960208260061b850101111561527c57600080fd5b9699959850939650602001949392505050565b600080600083850360808112156152a557600080fd5b84356152b081614dd0565b935060208501356152c081614dd0565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156152f257600080fd5b506040840190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561535857615358615300565b604052919050565b600067ffffffffffffffff82111561537a5761537a615300565b5060051b60200190565b600082601f83011261539557600080fd5b815160206153aa6153a583615360565b61532f565b82815260059290921b840181019181810190868411156153c957600080fd5b8286015b848110156153ed5780516153e081614dd0565b83529183019183016153cd565b509695505050505050565b60006020828403121561540a57600080fd5b815167ffffffffffffffff81111561542157600080fd5b614d2a84828501615384565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561546f5761546f61542d565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156154db576154db61542d565b500290565b6000602082840312156154f257600080fd5b813560048110614bb157600080fd5b848152602081018490526080810161551c6040830185615190565b6155296060830184615190565b95945050505050565b60006020828403121561554457600080fd5b5051919050565b60006020828403121561555d57600080fd5b81518015158114614bb157600080fd5b6000826155a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000828210156155ba576155ba61542d565b500390565b60005b838110156155da5781810151838201526020016155c2565b83811115611bd65750506000910152565b600081518084526156038160208601602086016155bf565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201526000614bae60408301846155eb565b60006001600160a01b0380861683528085166020840152506060604083015261552960608301846155eb565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261569a57600080fd5b83018035915067ffffffffffffffff8211156156b557600080fd5b6020019150600581901b3603821315614f2c57600080fd5b6000602082840312156156df57600080fd5b8151614bb181614dd0565b600080604083850312156156fd57600080fd5b825167ffffffffffffffff8082111561571557600080fd5b61572186838701615384565b935060209150818501518181111561573857600080fd5b85019050601f8101861361574b57600080fd5b80516157596153a582615360565b81815260059190911b8201830190838101908883111561577857600080fd5b928401925b828410156157965783518252928401929084019061577d565b80955050505050509250929050565b600080604083850312156157b857600080fd5b505080516020909101519092909150565b600082516157db8184602087016155bf565b9190910192915050565b6020815260006130ac60208301846155eb56fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729736574506f6f6c734173736574734469726563745472616e7366657228616464726573735b5d2c616464726573735b5d5b5d2c626f6f6c5b5d5b5d29a26469706673582212205f6f2758e0a194168e1ee21858c7de5575e3041602ba60b90cda24613fdac4b864736f6c634300080d0033", "devdoc": { "author": "Venus", "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", @@ -2192,7 +2192,7 @@ "notice": "To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)" }, "getAmountOut(uint256,address,address)": { - "notice": "To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)" + "notice": "To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut" }, "getPools(address)": { "notice": "Get the array of all pools addresses" @@ -2367,7 +2367,7 @@ "label": "conversionConfigurations", "offset": 0, "slot": "253", - "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5463_storage))" + "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5493_storage))" }, { "astId": 3371, @@ -2402,7 +2402,7 @@ "type": "t_array(t_uint256)45_storage" }, { - "astId": 5689, + "astId": 5719, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "assetsReserves", "offset": 0, @@ -2410,7 +2410,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5696, + "astId": 5726, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "poolsAssetsReserves", "offset": 0, @@ -2418,7 +2418,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 5699, + "astId": 5729, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "poolRegistry", "offset": 0, @@ -2426,7 +2426,7 @@ "type": "t_address" }, { - "astId": 5706, + "astId": 5736, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "poolsAssetsDirectTransfer", "offset": 0, @@ -2478,7 +2478,7 @@ "label": "contract ResilientOracle", "numberOfBytes": "20" }, - "t_enum(ConversionAccessibility)5455": { + "t_enum(ConversionAccessibility)5485": { "encoding": "inplace", "label": "enum IAbstractTokenConverter.ConversionAccessibility", "numberOfBytes": "1" @@ -2497,12 +2497,12 @@ "numberOfBytes": "32", "value": "t_mapping(t_address,t_bool)" }, - "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5463_storage))": { + "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5493_storage))": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => mapping(address => struct IAbstractTokenConverter.ConversionConfig))", "numberOfBytes": "32", - "value": "t_mapping(t_address,t_struct(ConversionConfig)5463_storage)" + "value": "t_mapping(t_address,t_struct(ConversionConfig)5493_storage)" }, "t_mapping(t_address,t_mapping(t_address,t_uint256))": { "encoding": "mapping", @@ -2511,12 +2511,12 @@ "numberOfBytes": "32", "value": "t_mapping(t_address,t_uint256)" }, - "t_mapping(t_address,t_struct(ConversionConfig)5463_storage)": { + "t_mapping(t_address,t_struct(ConversionConfig)5493_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct IAbstractTokenConverter.ConversionConfig)", "numberOfBytes": "32", - "value": "t_struct(ConversionConfig)5463_storage" + "value": "t_struct(ConversionConfig)5493_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2525,12 +2525,12 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_struct(ConversionConfig)5463_storage": { + "t_struct(ConversionConfig)5493_storage": { "encoding": "inplace", "label": "struct IAbstractTokenConverter.ConversionConfig", "members": [ { - "astId": 5458, + "astId": 5488, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "incentive", "offset": 0, @@ -2538,12 +2538,12 @@ "type": "t_uint256" }, { - "astId": 5462, + "astId": 5492, "contract": "contracts/TokenConverter/RiskFundConverter.sol:RiskFundConverter", "label": "conversionAccess", "offset": 0, "slot": "1", - "type": "t_enum(ConversionAccessibility)5455" + "type": "t_enum(ConversionAccessibility)5485" } ], "numberOfBytes": "64" diff --git a/deployments/bscmainnet/SingleTokenConverterImp.json b/deployments/bscmainnet/SingleTokenConverterImp.json index ab7f6f51..adf57368 100644 --- a/deployments/bscmainnet/SingleTokenConverterImp.json +++ b/deployments/bscmainnet/SingleTokenConverterImp.json @@ -1,5 +1,5 @@ { - "address": "0xe80f5A2adE24bEd740408B944197b3c24f2f2e91", + "address": "0x40ed28180Df01FdeB957224E4A5415704B9D5990", "abi": [ { "inputs": [], @@ -1381,39 +1381,39 @@ "type": "function" } ], - "transactionHash": "0x0c9ae239c95587f64fcb9fa83d860cf8a9284d9fd33cf7e3d0a353d50f2c43cd", + "transactionHash": "0x2ea2def33fea683485b21078cbb9dba47f76c54a8de89134f2a7654b4b3c733d", "receipt": { "to": null, "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0xe80f5A2adE24bEd740408B944197b3c24f2f2e91", - "transactionIndex": 57, - "gasUsed": "3622756", - "logsBloom": "0x00000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000", - "blockHash": "0xd495e0a03cd43795713811b28fe06b59c8ef761a646a89785f4f685110ec5bf4", - "transactionHash": "0x0c9ae239c95587f64fcb9fa83d860cf8a9284d9fd33cf7e3d0a353d50f2c43cd", + "contractAddress": "0x40ed28180Df01FdeB957224E4A5415704B9D5990", + "transactionIndex": 7, + "gasUsed": "3635848", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000400000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000001000000000000000000000", + "blockHash": "0xf8b6f5f1d10dcbcb020c1052a5d4be43e443bcd13cc941356fbfdc8e980878fe", + "transactionHash": "0x2ea2def33fea683485b21078cbb9dba47f76c54a8de89134f2a7654b4b3c733d", "logs": [ { - "transactionIndex": 57, - "blockNumber": 35140077, - "transactionHash": "0x0c9ae239c95587f64fcb9fa83d860cf8a9284d9fd33cf7e3d0a353d50f2c43cd", - "address": "0xe80f5A2adE24bEd740408B944197b3c24f2f2e91", + "transactionIndex": 7, + "blockNumber": 36531556, + "transactionHash": "0x2ea2def33fea683485b21078cbb9dba47f76c54a8de89134f2a7654b4b3c733d", + "address": "0x40ed28180Df01FdeB957224E4A5415704B9D5990", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "logIndex": 129, - "blockHash": "0xd495e0a03cd43795713811b28fe06b59c8ef761a646a89785f4f685110ec5bf4" + "logIndex": 26, + "blockHash": "0xf8b6f5f1d10dcbcb020c1052a5d4be43e443bcd13cc941356fbfdc8e980878fe" } ], - "blockNumber": 35140077, - "cumulativeGasUsed": "10120885", + "blockNumber": 36531556, + "cumulativeGasUsed": "4496863", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "d02e743d886d63634298edb2c3d7a019", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newBaseAsset\",\"type\":\"address\"}],\"name\":\"BaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"}],\"name\":\"setBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Balance of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256)\":{\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"Minimum amount to convert\",\"priceOracle_\":\"Resilient oracle address\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"baseAsset_\":\"The new address of the base asset\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"SingleTokenConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"BaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when base asset is updated\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"baseAsset()\":{\"notice\":\"Address of the base asset token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setBaseAsset(address)\":{\"notice\":\"Sets the base asset for the contract\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"SingleTokenConverter used for token conversions and sends received tokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/SingleTokenConverter.sol\":\"SingleTokenConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa =\\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\\n tokenInToOutConversion; //round-up\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa =\\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\\n (tokenOutUnderlyingPrice * EXP_SCALE);\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n}\\n\",\"keccak256\":\"0xe10a4505a941511a1e57e162dc5b7d6e4874e40ad421828bc4d6366b51b5608c\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/SingleTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\n\\n/// @title SingleTokenConverter\\n/// @author Venus\\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract SingleTokenConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the base asset token\\n address public baseAsset;\\n\\n /// @notice Emitted when base asset is updated\\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ Minimum amount to convert\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address baseAsset_,\\n uint256 minAmountToConvert_\\n ) public initializer {\\n _setBaseAsset(baseAsset_);\\n\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @notice Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:access Only Governance\\n function setBaseAsset(address baseAsset_) external onlyOwner {\\n _setBaseAsset(baseAsset_);\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n tokenBalance = token.balanceOf(address(this));\\n }\\n\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address.\\n /// @return balanceLeft Amount of asset, for _privateConversion\\n // solhint-disable-next-line\\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 balance = token.balanceOf(address(this));\\n balanceLeft = balance;\\n\\n if (asset == baseAsset) {\\n balanceLeft = 0;\\n token.safeTransfer(destinationAddress, balance);\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\\n }\\n }\\n\\n /// @dev Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n /// @custom:event BaseAssetUpdated is emitted on success\\n function _setBaseAsset(address baseAsset_) internal {\\n ensureNonzeroAddress(baseAsset_);\\n emit BaseAssetUpdated(baseAsset, baseAsset_);\\n baseAsset = baseAsset_;\\n }\\n\\n /// @dev Get base asset address\\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = baseAsset;\\n }\\n}\\n\",\"keccak256\":\"0xde2e9d5ef380a06a222825b11ffa47edad9e7624e3e90b8b55c92562f9216e76\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61408c80620000f36000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d4366004613802565b610562565b005b6102ee6102e936600461381f565b610576565b60408051928352602083019190915201610288565b6102d9610311366004613802565b610624565b60fc54610274906001600160a01b031681565b6102d9610337366004613802565b610635565b6102ee61034a366004613861565b610646565b6102d961035d366004613802565b610784565b6102d9610370366004613802565b610795565b6102d96107a6565b6102ee61038b36600461381f565b61088c565b6102d961039e3660046138c0565b610973565b6102ee6103b136600461381f565b610a10565b6102ee6103c436600461381f565b610b19565b6103dc6103d7366004613802565b610c18565b604051908152602001610288565b6102d9610ca5565b6102d9610400366004613901565b610cb9565b6102d9610d00565b6033546001600160a01b0316610274565b6102ee61042c366004613861565b610d90565b6102d961043f36600461391a565b610e7a565b61047961045236600461391a565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139bd565b6097546001600160a01b0316610274565b6102ee6104a6366004613861565b610eb0565b6102d9610f9a565b6102d96104c1366004613a1d565b61104c565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613861565b6110ea565b6102d961052e366004613ad1565b61120d565b6102d9610541366004613802565b6115ac565b6102d9610554366004613b42565b611635565b6103dc60fb5481565b61056a6117bf565b61057381611819565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b8613953565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610c18565b905085811015610608578095505b859250610616868686611896565b508092505050935093915050565b61062c6117bf565b61057381611bba565b61063d6117bf565b61057381611caf565b600080828585610654611d2e565b61065d83611d83565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611dc3565b6106da8a8a8a8a8a611e1c565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117bf565b61057381611ea3565b61079d6117bf565b61057381611f20565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611f9d565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce613953565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610915868686612069565b9092509050600061092585610c18565b9050828110156109695781600181610945670de0b6b3a764000085613bd5565b61094f9190613c12565b6109599190613c2a565b6109639190613c41565b93508092505b5050935093915050565b61097b6117bf565b610983611dc3565b61098c83611d83565b61099582611d83565b61099e8161238a565b826109b36001600160a01b03821684846123c4565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109f891815260200190565b60405180910390a350610a0b600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b50505050610b0f858585612069565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b7d57600080fd5b505af1158015610b91573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bf557600080fd5b505af1158015610c09573d6000803e3d6000fd5b50505050610b0f858585611896565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9e9190613c7c565b9392505050565b610cad6117bf565b610cb7600061248b565b565b610cf76040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611f9d565b610573816124bc565b60655433906001600160a01b03168114610d875760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6105738161248b565b600080828585610d9e611d2e565b610da783611d83565b816001600160a01b0316836001600160a01b03161480610dd85750806001600160a01b0316836001600160a01b0316145b15610e0f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e17611dc3565b610e248a8a8a8a8a611e1c565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e82611dc3565b6000610e8e8383612506565b90508015610ea157610ea183838361261b565b50610eac600160c955565b5050565b600080828585610ebe611d2e565b610ec783611d83565b816001600160a01b0316836001600160a01b03161480610ef85750806001600160a01b0316836001600160a01b0316145b15610f2f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f37611dc3565b610f448a8a8a8a8a612ad8565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fd86040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611f9d565b610fe0611d2e565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b82818114611086576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110e1576110d9878787848181106110a7576110a7613c95565b90506020020160208101906110bc9190613802565b8686858181106110ce576110ce613c95565b90506040020161120d565b600101611089565b50505050505050565b6000808285856110f8611d2e565b61110183611d83565b816001600160a01b0316836001600160a01b031614806111325750806001600160a01b0316836001600160a01b0316145b15611169576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611171611dc3565b61117e8a8a8a8a8a612b6a565b90955093508884146111bc576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61122e60405180606001604052806035815260200161402260359139611f9d565b61123783611d83565b61124082611d83565b6706f05b59d3b2000081351115611294576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d7e565b816001600160a01b0316836001600160a01b031614806112c3575061012d546001600160a01b03848116911614155b8061130b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561130857611308613953565b14155b15611342576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113546040830160208401613cc4565b600381111561136557611365613953565b1480156113725750803515155b156113a9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113bb6040830160208401613cc4565b60038111156113cc576113cc613953565b14806113f8575060016113e56040830160208401613cc4565b60038111156113f6576113f6613953565b145b801561140d575060ff546001600160a01b0316155b15611444576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff909116916114b491908a01908a01613cc4565b6040516114c49493929190613ce5565b60405180910390a360006114de6040840160208501613cc4565b60038111156114ef576114ef613953565b0361154c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556115a6565b813581556115606040830160208401613cc4565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115a0576115a0613953565b02179055505b50505050565b6115b46117bf565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115fd6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff16158080156116555750600054600160ff909116105b8061166f5750303b15801561166f575060005460ff166001145b6116e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d7e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561173f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61174883611caf565b61175486868685612c27565b80156117b757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610cb75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d7e565b61182281611d83565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118d3576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561192757611927613953565b600381111561193857611938613953565b905250905060008160200151600381111561195557611955613953565b0361198c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a149190613c7c565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613c7c565b835160ff54919250906001600160a01b031615801590611b41575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b419190613d16565b15611b4a575060005b6000611b5e82670de0b6b3a7640000613c12565b905082611b6b8286613bd5565b611b759190613c41565b955085600181611b8d670de0b6b3a76400008e613bd5565b611b979190613c12565b611ba19190613c2a565b611bab9190613c41565b96505050505050935093915050565b6001600160a01b038116611c365760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d7e565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611cb881611d83565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610cb7576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e155760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d7e565b600260c955565b600080611e298585612cc0565b611e338588612de0565b9150611e40828686610a10565b91505085811015611e87576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d7e565b611e92848483612f2b565b9550959350505050565b600160c955565b611eac81611d83565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f2981611d83565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab90611fe99033908690600401613dae565b602060405180830381865afa158015612006573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202a9190613d16565b905080610eac573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d7e93929190613dd0565b600080846000036120a6576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff1660038111156120fa576120fa613953565b600381111561210b5761210b613953565b905250905060008160200151600381111561212857612128613953565b0361215f576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e79190613c7c565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612250573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122749190613c7c565b835160ff54919250906001600160a01b031615801590612314575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa1580156122f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123149190613d16565b1561231d575060005b600061233182670de0b6b3a7640000613c12565b9050612345670de0b6b3a764000084613bd5565b81612350868d613bd5565b61235a9190613bd5565b6123649190613c41565b9650826123718286613bd5565b61237b9190613c41565b95505050505050935093915050565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610a0b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612f8e565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561057381613076565b6124c58161238a565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa15801561256a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258e9190613c7c565b61012d549093508391506001600160a01b03908116908516036126135760fe54600093506125c9906001600160a01b038481169116836123c4565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061263061012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612ad35760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126bf573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526127059190810190613f09565b8151919350915060005b81811015612ace5782818151811061272957612729613c95565b602002602001015160000315612ace57600084828151811061274d5761274d613c95565b60200260200101516001600160a01b0316636f1a30a885848151811061277557612775613c95565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127b7939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af11580156127d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f99190613fce565b915050888111156128075750875b612811818b6130e0565b61281b5750612ace565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613c7c565b90508a6001600160a01b031663095ea7b38785815181106128c5576128c5613c95565b6020026020010151846040518363ffffffff1660e01b81526004016128ff9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af115801561291e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129429190613d16565b5085838151811061295557612955613c95565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af11580156129df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a039190613fce565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c9190613c7c565b9050612a98838c613c2a565b9a50612aa48282613c2a565b612aae9089613c12565b97508a600003612ac057505050612ace565b83600101935050505061270f565b505050505b6117b7565b600080612ae58585612cc0565b6000612af2878787610b19565b91505087811115612b39576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612b438682612de0565b9250612b50838787610a10565b9250612b5f9050858584612f2b565b509550959350505050565b600080612b778585612cc0565b6000612b84878787610b19565b915050612b918682612de0565b9250808314612bcc576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c10576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612c1b858589612f2b565b50909694955050505050565b600054610100900460ff16612ca45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b612cad84613218565b612cb56132a6565b6115a683838361332b565b60ff546000906001600160a01b031615801590612d5d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5d9190613d16565b905080158015612da9575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612da757612da7613953565b145b15610a0b576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6d9190613c7c565b60fe54909150612e8c906001600160a01b0384811691339116876133f0565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f159190613c7c565b9050612f218282613c2a565b9695505050505050565b6000612f3684610c18565b905081811015612f72576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612f876001600160a01b03821685856123c4565b5050505050565b6000612fe3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134419092919063ffffffff16565b90508051600014806130045750808060200190518101906130049190613d16565b610a0b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d7e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561314157600080fd5b505af1158015613155573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156131c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ed9190613c7c565b6131f79190613bd5565b6132019190613c41565b905060fb54811061321157600191505b5092915050565b600054610100900460ff166132955760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b61329d613458565b610573816134dd565b600054610100900460ff166133235760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb761355a565b600054610100900460ff166133a85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6133b183611f20565b6133ba82611819565b6133c3816124bc565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b03808516602483015283166044820152606481018290526115a69085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612409565b606061345084846000856135d7565b949350505050565b600054610100900460ff166134d55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb76136c9565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b600054610100900460ff16611e9c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b60608247101561364f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d7e565b600080866001600160a01b0316858760405161366b9190613ff2565b60006040518083038185875af1925050503d80600081146136a8576040519150601f19603f3d011682016040523d82523d6000602084013e6136ad565b606091505b50915091506136be8783838761374f565b979650505050505050565b600054610100900460ff166137465760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb73361248b565b606083156137be5782516000036137b7576001600160a01b0385163b6137b75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d7e565b5081613450565b61345083838151156137d35781518083602001fd5b8060405162461bcd60e51b8152600401610d7e919061400e565b6001600160a01b038116811461057357600080fd5b60006020828403121561381457600080fd5b8135610c9e816137ed565b60008060006060848603121561383457600080fd5b833592506020840135613846816137ed565b91506040840135613856816137ed565b809150509250925092565b600080600080600060a0868803121561387957600080fd5b85359450602086013593506040860135613892816137ed565b925060608601356138a2816137ed565b915060808601356138b2816137ed565b809150509295509295909350565b6000806000606084860312156138d557600080fd5b83356138e0816137ed565b925060208401356138f0816137ed565b929592945050506040919091013590565b60006020828403121561391357600080fd5b5035919050565b6000806040838503121561392d57600080fd5b8235613938816137ed565b91506020830135613948816137ed565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139b9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c9e6020830184613982565b60008083601f8401126139e357600080fd5b50813567ffffffffffffffff8111156139fb57600080fd5b6020830191508360208260061b8501011115613a1657600080fd5b9250929050565b600080600080600060608688031215613a3557600080fd5b8535613a40816137ed565b9450602086013567ffffffffffffffff80821115613a5d57600080fd5b818801915088601f830112613a7157600080fd5b813581811115613a8057600080fd5b8960208260051b8501011115613a9557600080fd5b602083019650809550506040880135915080821115613ab357600080fd5b50613ac0888289016139d1565b969995985093965092949392505050565b60008060008385036080811215613ae757600080fd5b8435613af2816137ed565b93506020850135613b02816137ed565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b3457600080fd5b506040840190509250925092565b600080600080600060a08688031215613b5a57600080fd5b8535613b65816137ed565b94506020860135613b75816137ed565b93506040860135613b85816137ed565b92506060860135613b95816137ed565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c0d57613c0d613ba6565b500290565b60008219821115613c2557613c25613ba6565b500190565b600082821015613c3c57613c3c613ba6565b500390565b600082613c77577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613c8e57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613cd657600080fd5b813560048110610c9e57600080fd5b8481526020810184905260808101613d006040830185613982565b613d0d6060830184613982565b95945050505050565b600060208284031215613d2857600080fd5b81518015158114610c9e57600080fd5b60005b83811015613d53578181015183820152602001613d3b565b838111156115a65750506000910152565b60008151808452613d7c816020860160208601613d38565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134506040830184613d64565b60006001600160a01b03808616835280851660208401525060606040830152613d0d6060830184613d64565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613e7257613e72613dfc565b604052919050565b600067ffffffffffffffff821115613e9457613e94613dfc565b5060051b60200190565b600082601f830112613eaf57600080fd5b81516020613ec4613ebf83613e7a565b613e2b565b82815260059290921b84018101918181019086841115613ee357600080fd5b8286015b84811015613efe5780518352918301918301613ee7565b509695505050505050565b60008060408385031215613f1c57600080fd5b825167ffffffffffffffff80821115613f3457600080fd5b818501915085601f830112613f4857600080fd5b81516020613f58613ebf83613e7a565b82815260059290921b84018101918181019089841115613f7757600080fd5b948201945b83861015613f9e578551613f8f816137ed565b82529482019490820190613f7c565b91880151919650909350505080821115613fb757600080fd5b50613fc485828601613e9e565b9150509250929050565b60008060408385031215613fe157600080fd5b505080516020909101519092909150565b60008251614004818460208701613d38565b9190910192915050565b602081526000610c9e6020830184613d6456fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220fbd82e06735677bc9d44b30a618a4cd1179b2083744b3d0aafc0351f632f937464736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d4366004613802565b610562565b005b6102ee6102e936600461381f565b610576565b60408051928352602083019190915201610288565b6102d9610311366004613802565b610624565b60fc54610274906001600160a01b031681565b6102d9610337366004613802565b610635565b6102ee61034a366004613861565b610646565b6102d961035d366004613802565b610784565b6102d9610370366004613802565b610795565b6102d96107a6565b6102ee61038b36600461381f565b61088c565b6102d961039e3660046138c0565b610973565b6102ee6103b136600461381f565b610a10565b6102ee6103c436600461381f565b610b19565b6103dc6103d7366004613802565b610c18565b604051908152602001610288565b6102d9610ca5565b6102d9610400366004613901565b610cb9565b6102d9610d00565b6033546001600160a01b0316610274565b6102ee61042c366004613861565b610d90565b6102d961043f36600461391a565b610e7a565b61047961045236600461391a565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139bd565b6097546001600160a01b0316610274565b6102ee6104a6366004613861565b610eb0565b6102d9610f9a565b6102d96104c1366004613a1d565b61104c565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613861565b6110ea565b6102d961052e366004613ad1565b61120d565b6102d9610541366004613802565b6115ac565b6102d9610554366004613b42565b611635565b6103dc60fb5481565b61056a6117bf565b61057381611819565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b8613953565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610c18565b905085811015610608578095505b859250610616868686611896565b508092505050935093915050565b61062c6117bf565b61057381611bba565b61063d6117bf565b61057381611caf565b600080828585610654611d2e565b61065d83611d83565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611dc3565b6106da8a8a8a8a8a611e1c565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117bf565b61057381611ea3565b61079d6117bf565b61057381611f20565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611f9d565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce613953565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610915868686612069565b9092509050600061092585610c18565b9050828110156109695781600181610945670de0b6b3a764000085613bd5565b61094f9190613c12565b6109599190613c2a565b6109639190613c41565b93508092505b5050935093915050565b61097b6117bf565b610983611dc3565b61098c83611d83565b61099582611d83565b61099e8161238a565b826109b36001600160a01b03821684846123c4565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109f891815260200190565b60405180910390a350610a0b600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b50505050610b0f858585612069565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b7d57600080fd5b505af1158015610b91573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bf557600080fd5b505af1158015610c09573d6000803e3d6000fd5b50505050610b0f858585611896565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9e9190613c7c565b9392505050565b610cad6117bf565b610cb7600061248b565b565b610cf76040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611f9d565b610573816124bc565b60655433906001600160a01b03168114610d875760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6105738161248b565b600080828585610d9e611d2e565b610da783611d83565b816001600160a01b0316836001600160a01b03161480610dd85750806001600160a01b0316836001600160a01b0316145b15610e0f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e17611dc3565b610e248a8a8a8a8a611e1c565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e82611dc3565b6000610e8e8383612506565b90508015610ea157610ea183838361261b565b50610eac600160c955565b5050565b600080828585610ebe611d2e565b610ec783611d83565b816001600160a01b0316836001600160a01b03161480610ef85750806001600160a01b0316836001600160a01b0316145b15610f2f576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f37611dc3565b610f448a8a8a8a8a612ad8565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fd86040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611f9d565b610fe0611d2e565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b82818114611086576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110e1576110d9878787848181106110a7576110a7613c95565b90506020020160208101906110bc9190613802565b8686858181106110ce576110ce613c95565b90506040020161120d565b600101611089565b50505050505050565b6000808285856110f8611d2e565b61110183611d83565b816001600160a01b0316836001600160a01b031614806111325750806001600160a01b0316836001600160a01b0316145b15611169576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611171611dc3565b61117e8a8a8a8a8a612b6a565b90955093508884146111bc576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61122e60405180606001604052806035815260200161402260359139611f9d565b61123783611d83565b61124082611d83565b6706f05b59d3b2000081351115611294576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d7e565b816001600160a01b0316836001600160a01b031614806112c3575061012d546001600160a01b03848116911614155b8061130b575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff16600381111561130857611308613953565b14155b15611342576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113546040830160208401613cc4565b600381111561136557611365613953565b1480156113725750803515155b156113a9576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113bb6040830160208401613cc4565b60038111156113cc576113cc613953565b14806113f8575060016113e56040830160208401613cc4565b60038111156113f6576113f6613953565b145b801561140d575060ff546001600160a01b0316155b15611444576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff909116916114b491908a01908a01613cc4565b6040516114c49493929190613ce5565b60405180910390a360006114de6040840160208501613cc4565b60038111156114ef576114ef613953565b0361154c576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556115a6565b813581556115606040830160208401613cc4565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115a0576115a0613953565b02179055505b50505050565b6115b46117bf565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115fd6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff16158080156116555750600054600160ff909116105b8061166f5750303b15801561166f575060005460ff166001145b6116e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d7e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561173f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61174883611caf565b61175486868685612c27565b80156117b757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610cb75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d7e565b61182281611d83565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118d3576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561192757611927613953565b600381111561193857611938613953565b905250905060008160200151600381111561195557611955613953565b0361198c576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a149190613c7c565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613c7c565b835160ff54919250906001600160a01b031615801590611b41575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b419190613d16565b15611b4a575060005b6000611b5e82670de0b6b3a7640000613c12565b905082611b6b8286613bd5565b611b759190613c41565b955085600181611b8d670de0b6b3a76400008e613bd5565b611b979190613c12565b611ba19190613c2a565b611bab9190613c41565b96505050505050935093915050565b6001600160a01b038116611c365760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d7e565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611cb881611d83565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610cb7576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e155760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d7e565b600260c955565b600080611e298585612cc0565b611e338588612de0565b9150611e40828686610a10565b91505085811015611e87576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d7e565b611e92848483612f2b565b9550959350505050565b600160c955565b611eac81611d83565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f2981611d83565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab90611fe99033908690600401613dae565b602060405180830381865afa158015612006573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202a9190613d16565b905080610eac573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d7e93929190613dd0565b600080846000036120a6576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff1660038111156120fa576120fa613953565b600381111561210b5761210b613953565b905250905060008160200151600381111561212857612128613953565b0361215f576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e79190613c7c565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612250573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122749190613c7c565b835160ff54919250906001600160a01b031615801590612314575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa1580156122f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123149190613d16565b1561231d575060005b600061233182670de0b6b3a7640000613c12565b9050612345670de0b6b3a764000084613bd5565b81612350868d613bd5565b61235a9190613bd5565b6123649190613c41565b9650826123718286613bd5565b61237b9190613c41565b95505050505050935093915050565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610a0b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612f8e565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561057381613076565b6124c58161238a565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa15801561256a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258e9190613c7c565b61012d549093508391506001600160a01b03908116908516036126135760fe54600093506125c9906001600160a01b038481169116836123c4565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061263061012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612ad35760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126bf573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526127059190810190613f09565b8151919350915060005b81811015612ace5782818151811061272957612729613c95565b602002602001015160000315612ace57600084828151811061274d5761274d613c95565b60200260200101516001600160a01b0316636f1a30a885848151811061277557612775613c95565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127b7939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af11580156127d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f99190613fce565b915050888111156128075750875b612811818b6130e0565b61281b5750612ace565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613c7c565b90508a6001600160a01b031663095ea7b38785815181106128c5576128c5613c95565b6020026020010151846040518363ffffffff1660e01b81526004016128ff9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af115801561291e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129429190613d16565b5085838151811061295557612955613c95565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af11580156129df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a039190613fce565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c9190613c7c565b9050612a98838c613c2a565b9a50612aa48282613c2a565b612aae9089613c12565b97508a600003612ac057505050612ace565b83600101935050505061270f565b505050505b6117b7565b600080612ae58585612cc0565b6000612af2878787610b19565b91505087811115612b39576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612b438682612de0565b9250612b50838787610a10565b9250612b5f9050858584612f2b565b509550959350505050565b600080612b778585612cc0565b6000612b84878787610b19565b915050612b918682612de0565b9250808314612bcc576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c10576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d7e565b612c1b858589612f2b565b50909694955050505050565b600054610100900460ff16612ca45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b612cad84613218565b612cb56132a6565b6115a683838361332b565b60ff546000906001600160a01b031615801590612d5d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5d9190613d16565b905080158015612da9575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612da757612da7613953565b145b15610a0b576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6d9190613c7c565b60fe54909150612e8c906001600160a01b0384811691339116876133f0565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f159190613c7c565b9050612f218282613c2a565b9695505050505050565b6000612f3684610c18565b905081811015612f72576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612f876001600160a01b03821685856123c4565b5050505050565b6000612fe3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134419092919063ffffffff16565b90508051600014806130045750808060200190518101906130049190613d16565b610a0b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d7e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561314157600080fd5b505af1158015613155573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa1580156131c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ed9190613c7c565b6131f79190613bd5565b6132019190613c41565b905060fb54811061321157600191505b5092915050565b600054610100900460ff166132955760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b61329d613458565b610573816134dd565b600054610100900460ff166133235760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb761355a565b600054610100900460ff166133a85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b6133b183611f20565b6133ba82611819565b6133c3816124bc565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b03808516602483015283166044820152606481018290526115a69085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612409565b606061345084846000856135d7565b949350505050565b600054610100900460ff166134d55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb76136c9565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b600054610100900460ff16611e9c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b60608247101561364f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d7e565b600080866001600160a01b0316858760405161366b9190613ff2565b60006040518083038185875af1925050503d80600081146136a8576040519150601f19603f3d011682016040523d82523d6000602084013e6136ad565b606091505b50915091506136be8783838761374f565b979650505050505050565b600054610100900460ff166137465760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d7e565b610cb73361248b565b606083156137be5782516000036137b7576001600160a01b0385163b6137b75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d7e565b5081613450565b61345083838151156137d35781518083602001fd5b8060405162461bcd60e51b8152600401610d7e919061400e565b6001600160a01b038116811461057357600080fd5b60006020828403121561381457600080fd5b8135610c9e816137ed565b60008060006060848603121561383457600080fd5b833592506020840135613846816137ed565b91506040840135613856816137ed565b809150509250925092565b600080600080600060a0868803121561387957600080fd5b85359450602086013593506040860135613892816137ed565b925060608601356138a2816137ed565b915060808601356138b2816137ed565b809150509295509295909350565b6000806000606084860312156138d557600080fd5b83356138e0816137ed565b925060208401356138f0816137ed565b929592945050506040919091013590565b60006020828403121561391357600080fd5b5035919050565b6000806040838503121561392d57600080fd5b8235613938816137ed565b91506020830135613948816137ed565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139b9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c9e6020830184613982565b60008083601f8401126139e357600080fd5b50813567ffffffffffffffff8111156139fb57600080fd5b6020830191508360208260061b8501011115613a1657600080fd5b9250929050565b600080600080600060608688031215613a3557600080fd5b8535613a40816137ed565b9450602086013567ffffffffffffffff80821115613a5d57600080fd5b818801915088601f830112613a7157600080fd5b813581811115613a8057600080fd5b8960208260051b8501011115613a9557600080fd5b602083019650809550506040880135915080821115613ab357600080fd5b50613ac0888289016139d1565b969995985093965092949392505050565b60008060008385036080811215613ae757600080fd5b8435613af2816137ed565b93506020850135613b02816137ed565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b3457600080fd5b506040840190509250925092565b600080600080600060a08688031215613b5a57600080fd5b8535613b65816137ed565b94506020860135613b75816137ed565b93506040860135613b85816137ed565b92506060860135613b95816137ed565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c0d57613c0d613ba6565b500290565b60008219821115613c2557613c25613ba6565b500190565b600082821015613c3c57613c3c613ba6565b500390565b600082613c77577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613c8e57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613cd657600080fd5b813560048110610c9e57600080fd5b8481526020810184905260808101613d006040830185613982565b613d0d6060830184613982565b95945050505050565b600060208284031215613d2857600080fd5b81518015158114610c9e57600080fd5b60005b83811015613d53578181015183820152602001613d3b565b838111156115a65750506000910152565b60008151808452613d7c816020860160208601613d38565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134506040830184613d64565b60006001600160a01b03808616835280851660208401525060606040830152613d0d6060830184613d64565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613e7257613e72613dfc565b604052919050565b600067ffffffffffffffff821115613e9457613e94613dfc565b5060051b60200190565b600082601f830112613eaf57600080fd5b81516020613ec4613ebf83613e7a565b613e2b565b82815260059290921b84018101918181019086841115613ee357600080fd5b8286015b84811015613efe5780518352918301918301613ee7565b509695505050505050565b60008060408385031215613f1c57600080fd5b825167ffffffffffffffff80821115613f3457600080fd5b818501915085601f830112613f4857600080fd5b81516020613f58613ebf83613e7a565b82815260059290921b84018101918181019089841115613f7757600080fd5b948201945b83861015613f9e578551613f8f816137ed565b82529482019490820190613f7c565b91880151919650909350505080821115613fb757600080fd5b50613fc485828601613e9e565b9150509250929050565b60008060408385031215613fe157600080fd5b505080516020909101519092909150565b60008251614004818460208701613d38565b9190910192915050565b602081526000610c9e6020830184613d6456fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220fbd82e06735677bc9d44b30a618a4cd1179b2083744b3d0aafc0351f632f937464736f6c634300080d0033", + "numDeployments": 2, + "solcInputHash": "91b55240df7761b1edcdbbc6fc102117", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountInHigherThanMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountInMismatched\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"}],\"name\":\"AmountOutLowerThanMinRequired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountOutMismatched\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionConfigNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionEnabledOnlyForPrivateConversions\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConversionTokensPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeflationaryTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxIncentive\",\"type\":\"uint256\"}],\"name\":\"IncentiveTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputLengthMisMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientOutputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPoolLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConverterNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimumAmountToConvert\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenConfigAddresses\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroIncentiveForPrivateConversion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetTransferredToDestination\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newBaseAsset\",\"type\":\"address\"}],\"name\":\"BaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newIncentive\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"oldAccess\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"newAccess\",\"type\":\"uint8\"}],\"name\":\"ConversionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ConversionResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"ConvertedForExactTokensSupportingFeeOnTransferTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConverterNetwork\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"converterNetwork\",\"type\":\"address\"}],\"name\":\"ConverterNetworkAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldDestinationAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"}],\"name\":\"DestinationAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle\",\"type\":\"address\"}],\"name\":\"PriceOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_INCENTIVE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"conversionConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"conversionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMaxMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"convertForExactTokensSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAmountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualAmountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"converterNetwork\",\"outputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destinationAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountInMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"}],\"name\":\"getUpdatedAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountConvertedMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceOracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resumeConversion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"baseAsset_\",\"type\":\"address\"}],\"name\":\"setBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddressOut\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig\",\"name\":\"conversionConfig\",\"type\":\"tuple\"}],\"name\":\"setConversionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddressIn\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddressesOut\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"incentive\",\"type\":\"uint256\"},{\"internalType\":\"enum IAbstractTokenConverter.ConversionAccessibility\",\"name\":\"conversionAccess\",\"type\":\"uint8\"}],\"internalType\":\"struct IAbstractTokenConverter.ConversionConfig[]\",\"name\":\"conversionConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConversionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConverterNetwork\",\"name\":\"converterNetwork_\",\"type\":\"address\"}],\"name\":\"setConverterNetwork\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destinationAddress_\",\"type\":\"address\"}],\"name\":\"setDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracle\",\"name\":\"priceOracle_\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"balanceOf(address)\":{\"params\":{\"tokenAddress\":\"Address of the token\"},\"returns\":{\"tokenBalance\":\"Balance of the token the contract has\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissaAmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\",\"custom:event\":\"Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"amountOutMinMantissa\":\"Min amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissaAmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\",\"custom:event\":\"Emits ConvertedForExactTokens event on success\",\"details\":\"Method does not support deflationary tokens transfer\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when to address is zeroInvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOutAmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\",\"custom:event\":\"Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\",\"params\":{\"amountInMaxMantissa\":\"Max amount of tokenAddressIn\",\"amountOutMantissa\":\"Amount of tokenAddressOut required as output\",\"to\":\"Address of the tokenAddressOut receiver\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"actualAmountIn\":\"Actual amount transferred to destination\",\"actualAmountOut\":\"Actual amount transferred to user\"}},\"getAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pairConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\",\"details\":\"This function retrieves values without altering token prices\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"getUpdatedAmountIn(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountOutMantissa\":\"Amount of tokenAddressOut user wants to receive\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressOut should be transferred after conversion\",\"amountInMantissa\":\"Amount of the tokenAddressIn sender would send to contract before conversion\"}},\"getUpdatedAmountOut(uint256,address,address)\":{\"custom:error\":\"InsufficientInputAmount error is thrown when given input amount is zeroConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\",\"params\":{\"amountInMantissa\":\"Amount of tokenAddressIn\",\"tokenAddressIn\":\"Address of the token to convert\",\"tokenAddressOut\":\"Address of the token to get after conversion\"},\"returns\":{\"amountConvertedMantissa\":\"Amount of tokenAddressIn should be transferred after conversion\",\"amountOutMantissa\":\"Amount of the tokenAddressOut sender should receive after conversion\"}},\"initialize(address,address,address,address,uint256)\":{\"params\":{\"accessControlManager_\":\"Access control manager contract address\",\"baseAsset_\":\"Address of the base asset\",\"destinationAddress_\":\"Address at all incoming tokens will transferred to\",\"minAmountToConvert_\":\"Minimum amount to convert\",\"priceOracle_\":\"Resilient oracle address\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pauseConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensPaused thrown when conversion is already paused\",\"custom:event\":\"Emits ConversionPaused on success\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"resumeConversion()\":{\"custom:access\":\"Restricted by ACM\",\"custom:error\":\"ConversionTokensActive thrown when conversion is already active\",\"custom:event\":\"Emits ConversionResumed on success\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"baseAsset_\":\"The new address of the base asset\"}},\"setConversionConfig(address,address,(uint256,uint8))\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerZeroAddressNotAllowed is thrown when pool registry address is zeroNonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\",\"custom:event\":\"Emits ConversionConfigUpdated event on success\",\"params\":{\"conversionConfig\":\"ConversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressOut\":\"Address of tokenOut\"}},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"custom:error\":\"InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\",\"params\":{\"conversionConfigs\":\"Array of conversionConfig config details to update\",\"tokenAddressIn\":\"Address of tokenIn\",\"tokenAddressesOut\":\"Array of addresses of tokenOut\"}},\"setConverterNetwork(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"converterNetwork_\":\"The converterNetwork address to be set\"}},\"setDestination(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"destinationAddress_\":\"The new destination address to be set\"}},\"setMinAmountToConvert(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"minAmountToConvert_\":\"Min amount to convert\"}},\"setPriceOracle(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"priceOracle_\":\"Address of the new price oracle to set\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"The amount to transfer\",\"to\":\"The address to which tokens will be transferred\",\"tokenAddress\":\"The address of the ERC-20 token to sweep\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address)\":{\"details\":\"This function is called by protocolShareReservecall _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\",\"params\":{\"asset\":\"Asset address\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"SingleTokenConverter\",\"version\":1},\"userdoc\":{\"errors\":{\"AmountInHigherThanMax(uint256,uint256)\":[{\"notice\":\"Thrown when amountIn is higher than amountInMax\"}],\"AmountInMismatched()\":[{\"notice\":\"Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\"}],\"AmountOutLowerThanMinRequired(uint256,uint256)\":[{\"notice\":\"Thrown when amountOut is lower than amountOutMin\"}],\"AmountOutMismatched()\":[{\"notice\":\"Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\"}],\"ConversionConfigNotEnabled()\":[{\"notice\":\"Thrown when conversion is disabled or config does not exist for given pair\"}],\"ConversionEnabledOnlyForPrivateConversions()\":[{\"notice\":\"Thrown when conversion is enabled only for private conversions\"}],\"ConversionTokensActive()\":[{\"notice\":\"Thrown when conversion is Active\"}],\"ConversionTokensPaused()\":[{\"notice\":\"Thrown when conversion is paused\"}],\"DeflationaryTokenNotSupported()\":[{\"notice\":\"Thrown when using convertForExactTokens deflationary tokens\"}],\"IncentiveTooHigh(uint256,uint256)\":[{\"notice\":\"Thrown when incentive is higher than the MAX_INCENTIVE\"}],\"InputLengthMisMatch()\":[{\"notice\":\"Thrown when there is a mismatch in the length of input arrays\"}],\"InsufficientInputAmount()\":[{\"notice\":\"Thrown when given input amount is zero\"}],\"InsufficientOutputAmount()\":[{\"notice\":\"Thrown when given output amount is zero\"}],\"InsufficientPoolLiquidity()\":[{\"notice\":\"Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\"}],\"InvalidConverterNetwork()\":[{\"notice\":\"When address of the ConverterNetwork is not set or Zero address\"}],\"InvalidMinimumAmountToConvert()\":[{\"notice\":\"Thrown when minimum amount to convert is zero\"}],\"InvalidToAddress()\":[{\"notice\":\"Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\"}],\"InvalidTokenConfigAddresses()\":[{\"notice\":\"Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\"}],\"NonZeroIncentiveForPrivateConversion()\":[{\"notice\":\"Thrown when trying to set non zero incentive for private conversion\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"AssetTransferredToDestination(address,address,address,uint256)\":{\"notice\":\"Emmitted after the funds transferred to the destination address\"},\"BaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when base asset is updated\"},\"ConversionConfigUpdated(address,address,uint256,uint256,uint8,uint8)\":{\"notice\":\"Emitted when config is updated for tokens pair\"},\"ConversionPaused(address)\":{\"notice\":\"Emitted when conversion is paused\"},\"ConversionResumed(address)\":{\"notice\":\"Emitted when conversion is unpaused\"},\"ConvertedExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens\"},\"ConvertedExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\"},\"ConvertedForExactTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens\"},\"ConvertedForExactTokensSupportingFeeOnTransferTokens(address,address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\"},\"ConverterNetworkAddressUpdated(address,address)\":{\"notice\":\"Emitted when converterNetwork address is updated\"},\"DestinationAddressUpdated(address,address)\":{\"notice\":\"Emitted when destination address is updated\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PriceOracleUpdated(address,address)\":{\"notice\":\"Emitted when price oracle address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"}},\"kind\":\"user\",\"methods\":{\"MAX_INCENTIVE()\":{\"notice\":\"Maximum incentive could be\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"balanceOf(address)\":{\"notice\":\"Get the balance for specific token\"},\"baseAsset()\":{\"notice\":\"Address of the base asset token\"},\"conversionConfigurations(address,address)\":{\"notice\":\"conversion configurations for the existing pairs\"},\"conversionPaused()\":{\"notice\":\"Boolean for if conversion is paused\"},\"convertExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\"},\"convertForExactTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract, otherwise the amount is adjusted\"},\"convertForExactTokensSupportingFeeOnTransferTokens(uint256,uint256,address,address,address)\":{\"notice\":\"Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted. The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\"},\"converterNetwork()\":{\"notice\":\"Address of the converterNetwork contract\"},\"destinationAddress()\":{\"notice\":\"Address that all incoming tokens are transferred to\"},\"getAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)\"},\"getAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\"},\"getUpdatedAmountIn(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\"},\"getUpdatedAmountOut(uint256,address,address)\":{\"notice\":\"To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\"},\"minAmountToConvert()\":{\"notice\":\"Min amount to convert for private conversions. Defined in USD, with 18 decimals\"},\"pauseConversion()\":{\"notice\":\"Pause conversion of tokens\"},\"priceOracle()\":{\"notice\":\"Venus price oracle contract\"},\"resumeConversion()\":{\"notice\":\"Resume conversion of tokens.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setBaseAsset(address)\":{\"notice\":\"Sets the base asset for the contract\"},\"setConversionConfig(address,address,(uint256,uint8))\":{\"notice\":\"Set the configuration for new or existing conversion pair\"},\"setConversionConfigs(address,address[],(uint256,uint8)[])\":{\"notice\":\"Batch sets the conversion configurations\"},\"setConverterNetwork(address)\":{\"notice\":\"Sets a converter network contract address\"},\"setDestination(address)\":{\"notice\":\"Sets a new destination address\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"To sweep ERC20 tokens and transfer them to user(to address)\"},\"updateAssetsState(address,address)\":{\"notice\":\"This method updated the states of this contract after getting funds from PSR after settling the amount(if any) through privateConversion between converters\"}},\"notice\":\"SingleTokenConverter used for token conversions and sends received tokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TokenConverter/SingleTokenConverter.sol\":\"SingleTokenConverter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"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\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/ResilientOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n// SPDX-FileCopyrightText: 2022 Venus\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./interfaces/VBep20Interface.sol\\\";\\nimport \\\"./interfaces/OracleInterface.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\n/**\\n * @title ResilientOracle\\n * @author Venus\\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\\n * \\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\\n * for attacking the protocol.\\n * \\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\\n * \\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \\n * \\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\\n * market. The upper bound ratio represents the deviation between reported price (the price that\\u2019s being\\n * validated) and the anchor price (the price we are validating against) above which the reported price will\\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\\n * should be true:\\n\\n```\\nanchorRatio = anchorPrice/reporterPrice\\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\\n```\\n\\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \\n * \\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\\n * oracle to be stagnant and treat it like it's disabled.\\n */\\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\\n /**\\n * @dev Oracle roles:\\n * **main**: The most trustworthy price source\\n * **pivot**: Price oracle used as a loose sanity checker\\n * **fallback**: The backup source when main oracle price is invalidated\\n */\\n enum OracleRole {\\n MAIN,\\n PIVOT,\\n FALLBACK\\n }\\n\\n struct TokenConfig {\\n /// @notice asset address\\n address asset;\\n /// @notice `oracles` stores the oracles based on their role in the following order:\\n /// [main, pivot, fallback],\\n /// It can be indexed with the corresponding enum OracleRole value\\n address[3] oracles;\\n /// @notice `enableFlagsForOracles` stores the enabled state\\n /// for each oracle in the same order as `oracles`\\n bool[3] enableFlagsForOracles;\\n }\\n\\n uint256 public constant INVALID_PRICE = 0;\\n\\n /// @notice Native market address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable nativeMarket;\\n\\n /// @notice VAI address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vai;\\n\\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\\n /// and can serve as any underlying asset of a market that supports native tokens\\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\\n\\n /// @notice Bound validator contract address\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n BoundValidatorInterface public immutable boundValidator;\\n\\n mapping(address => TokenConfig) private tokenConfigs;\\n\\n event TokenConfigAdded(\\n address indexed asset,\\n address indexed mainOracle,\\n address indexed pivotOracle,\\n address fallbackOracle\\n );\\n\\n /// Event emitted when an oracle is set\\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\\n\\n /// Event emitted when an oracle is enabled or disabled\\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\\n\\n /**\\n * @notice Checks whether an address is null or not\\n */\\n modifier notNullAddress(address someone) {\\n if (someone == address(0)) revert(\\\"can't be zero address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks whether token config exists by checking whether asset is null address\\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\\n * @param asset asset address\\n */\\n modifier checkTokenConfigExistence(address asset) {\\n if (tokenConfigs[asset].asset == address(0)) revert(\\\"token config must exist\\\");\\n _;\\n }\\n\\n /// @notice Constructor for the implementation contract. Sets immutable variables.\\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\\n /// (e.g vETH on ethereum would not be supported, only vWETH)\\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\\n /// Set to address(0) of VAI is not existent.\\n /// @param _boundValidator Address of the bound validator contract\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address nativeMarketAddress,\\n address vaiAddress,\\n BoundValidatorInterface _boundValidator\\n ) notNullAddress(address(_boundValidator)) {\\n nativeMarket = nativeMarketAddress;\\n vai = vaiAddress;\\n boundValidator = _boundValidator;\\n\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract admin and sets the BoundValidator contract address\\n * @param accessControlManager_ Address of the access control manager contract\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __AccessControlled_init(accessControlManager_);\\n __Pausable_init();\\n }\\n\\n /**\\n * @notice Pauses oracle\\n * @custom:access Only Governance\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n _pause();\\n }\\n\\n /**\\n * @notice Unpauses oracle\\n * @custom:access Only Governance\\n */\\n function unpause() external {\\n _checkAccessAllowed(\\\"unpause()\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Batch sets token configs\\n * @param tokenConfigs_ Token config array\\n * @custom:access Only Governance\\n * @custom:error Throws a length error if the length of the token configs array is 0\\n */\\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\\n if (tokenConfigs_.length == 0) revert(\\\"length can't be 0\\\");\\n uint256 numTokenConfigs = tokenConfigs_.length;\\n for (uint256 i; i < numTokenConfigs; ) {\\n setTokenConfig(tokenConfigs_[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Sets oracle for a given asset and role.\\n * @dev Supplied asset **must** exist and main oracle may not be null\\n * @param asset Asset address\\n * @param oracle Oracle address\\n * @param role Oracle role\\n * @custom:access Only Governance\\n * @custom:error Null address error if main-role oracle address is null\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\\n */\\n function setOracle(\\n address asset,\\n address oracle,\\n OracleRole role\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"setOracle(address,address,uint8)\\\");\\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\\\"can't set zero address to main oracle\\\");\\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\\n emit OracleSet(asset, oracle, uint256(role));\\n }\\n\\n /**\\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\\n * @param asset Asset address\\n * @param role Oracle role\\n * @param enable Enabled boolean of the oracle\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress error is thrown if asset address is null\\n * @custom:error TokenConfigExistance error is thrown if token config is not set\\n */\\n function enableOracle(\\n address asset,\\n OracleRole role,\\n bool enable\\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\\n _checkAccessAllowed(\\\"enableOracle(address,uint8,bool)\\\");\\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\\n emit OracleEnabled(asset, uint256(role), enable);\\n }\\n\\n /**\\n * @notice Updates the TWAP pivot oracle price.\\n * @dev This function should always be called before calling getUnderlyingPrice\\n * @param vToken vToken address\\n */\\n function updatePrice(address vToken) external override {\\n address asset = _getUnderlyingAsset(vToken);\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @notice Updates the pivot oracle price. Currently using TWAP\\n * @dev This function should always be called before calling getPrice\\n * @param asset asset address\\n */\\n function updateAssetPrice(address asset) external {\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracle != address(0) && pivotOracleEnabled) {\\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\\n }\\n }\\n\\n /**\\n * @dev Gets token config by asset address\\n * @param asset asset address\\n * @return tokenConfig Config for the asset\\n */\\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\\n return tokenConfigs[asset];\\n }\\n\\n /**\\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\\n * - Check if the oracle is paused globally\\n * - Validate price from main oracle against pivot oracle\\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\\n * - Validate price from main oracle against fallback oracle if the second validation failed\\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\\n * main oracle price is returned.\\n * @param vToken vToken address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n\\n address asset = _getUnderlyingAsset(vToken);\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Gets price of the asset\\n * @param asset asset address\\n * @return price USD price in scaled decimal places.\\n * @custom:error Paused error is thrown when resilent oracle is paused\\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\\n */\\n function getPrice(address asset) external view override returns (uint256) {\\n if (paused()) revert(\\\"resilient oracle is paused\\\");\\n return _getPrice(asset);\\n }\\n\\n /**\\n * @notice Sets/resets single token configs.\\n * @dev main oracle **must not** be a null address\\n * @param tokenConfig Token config struct\\n * @custom:access Only Governance\\n * @custom:error NotNullAddress is thrown if asset address is null\\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\\n */\\n function setTokenConfig(\\n TokenConfig memory tokenConfig\\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\\n _checkAccessAllowed(\\\"setTokenConfig(TokenConfig)\\\");\\n\\n tokenConfigs[tokenConfig.asset] = tokenConfig;\\n emit TokenConfigAdded(\\n tokenConfig.asset,\\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\\n );\\n }\\n\\n /**\\n * @notice Gets oracle and enabled status by asset address\\n * @param asset asset address\\n * @param role Oracle role\\n * @return oracle Oracle address based on role\\n * @return enabled Enabled flag of the oracle based on token config\\n */\\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\\n oracle = tokenConfigs[asset].oracles[uint256(role)];\\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\\n }\\n\\n function _getPrice(address asset) internal view returns (uint256) {\\n uint256 pivotPrice = INVALID_PRICE;\\n\\n // Get pivot oracle price, Invalid price if not available or error\\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\\n if (pivotOracleEnabled && pivotOracle != address(0)) {\\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\\n pivotPrice = pricePivot;\\n } catch {}\\n }\\n\\n // Compare main price and pivot price, return main price and if validation was successful\\n // note: In case pivot oracle is not available but main price is available and\\n // validation is successful, the main oracle price is returned.\\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\\n asset,\\n pivotPrice,\\n pivotOracleEnabled && pivotOracle != address(0)\\n );\\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\\n\\n // Compare fallback and pivot if main oracle comparision fails with pivot\\n // Return fallback price when fallback price is validated successfully with pivot oracle\\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\\n\\n // Lastly compare main price and fallback price\\n if (\\n mainPrice != INVALID_PRICE &&\\n fallbackPrice != INVALID_PRICE &&\\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\\n ) {\\n return mainPrice;\\n }\\n\\n revert(\\\"invalid resilient oracle price\\\");\\n }\\n\\n /**\\n * @notice Gets a price for the provided asset\\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\\n * able to fetch a correct price\\n * @param asset asset address\\n * @param pivotPrice Pivot oracle price\\n * @param pivotEnabled If pivot oracle is not empty and enabled\\n * @return price USD price in scaled decimals\\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\\n * @return pivotValidated Boolean representing if the validation of main oracle price\\n * and pivot oracle price were successful\\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\\n * address is null\\n */\\n function _getMainOraclePrice(\\n address asset,\\n uint256 pivotPrice,\\n bool pivotEnabled\\n ) internal view returns (uint256, bool) {\\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\\n if (mainOracleEnabled && mainOracle != address(0)) {\\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\\n if (!pivotEnabled) {\\n return (mainOraclePrice, true);\\n }\\n if (pivotPrice == INVALID_PRICE) {\\n return (mainOraclePrice, false);\\n }\\n return (\\n mainOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\\n * @param asset asset address\\n * @return price USD price in 18 decimals\\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\\n * and pivot oracle price were successfull\\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\\n * address is null\\n */\\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\\n if (fallbackEnabled && fallbackOracle != address(0)) {\\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\\n if (pivotPrice == INVALID_PRICE) {\\n return (fallbackOraclePrice, false);\\n }\\n return (\\n fallbackOraclePrice,\\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\\n );\\n } catch {\\n return (INVALID_PRICE, false);\\n }\\n }\\n\\n return (INVALID_PRICE, false);\\n }\\n\\n /**\\n * @dev This function returns the underlying asset of a vToken\\n * @param vToken vToken address\\n * @return asset underlying asset address\\n */\\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\\n if (vToken == nativeMarket) {\\n asset = NATIVE_TOKEN_ADDR;\\n } else if (vToken == vai) {\\n asset = vai;\\n } else {\\n asset = VBep20Interface(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3bead63c5f2aca7e1ea5e9a075816e9e3551ce3a886f5f3707040262ad6d2c35\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x40031b19684ca0c912e794d08c2c0b0d8be77d3c1bdc937830a0658eff899650\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\ninterface VBep20Interface is IERC20Metadata {\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3f845cd51b2d82f7932ac6c0ab714df97f733b01ce50f6fb0adb4c28447d4618\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x0464dd1b882ea2925e06e967c025a232c824e9e4c7aee7b97cc255d040594a59\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IConverterNetwork.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAbstractTokenConverter } from \\\"../TokenConverter/IAbstractTokenConverter.sol\\\";\\n\\n/**\\n * @title IConverterNetwork\\n * @author Venus\\n * @notice Interface implemented by `ConverterNetwork`.\\n */\\ninterface IConverterNetwork {\\n /// @notice Adds new converter to the array\\n /// @param _tokenConverter Address of the token converter\\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Removes converter from the array\\n /// @param _tokenConverter Address of the token converter\\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\\n /// @param _tokenAddressIn Address of tokenIn\\n /// @param _tokenAddressOut Address of tokenOut\\n /// @return converters Array of the conveters on the basis of the tokens pair\\n /// @return convertersBalance Array of balances with respect to token out\\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\\n external\\n returns (address[] memory converters, uint256[] memory convertersBalance);\\n\\n /// @notice This function returns the array containing all the converters addresses\\n /// @return Array containing all the converters addresses\\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\\n\\n /// @notice This function checks for given address is converter or not\\n /// @param _tokenConverter Address of the token converter\\n /// @return boolean true if given address is converter otherwise false\\n function isTokenConverter(address _tokenConverter) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x185dac944af690a34378319c568454fb7ce917c2ab6acdb514eec02e00965107\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/AbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { MANTISSA_ONE, EXP_SCALE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\nimport { IAbstractTokenConverter } from \\\"./IAbstractTokenConverter.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @title AbstractTokenConverter\\n/// @author Venus\\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\\n/*\\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\\n *\\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\\n * a. convertExactTokensSupportingFeeOnTransferTokens\\n * b. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\\n * similar to Case I.\\n *\\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * a. convertExactTokens\\n * b. convertForExactTokens\\n * c. convertExactTokensSupportingFeeOnTransferTokens\\n * d. convertForExactTokensSupportingFeeOnTransferTokens\\n *\\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\\n * similar to Case III.\\n *\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n * Example 1:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInAmount - 100\\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\\n * function for tokenIn as deflationary token.\\n *\\n * Example 2:-\\n * tokenInAddress - 0xaaaa.....\\n * tokenOutAddress - 0xbbbb.....\\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\\n * tokenOutAmount - 70\\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\\n * ------------------------------------------------------------------------------------------------------------------------------------\\n *\\n * This contract also supports private conversion between the converters:\\n * Private conversions:\\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\\n *\\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\\n *\\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\\n * tokenAddressOut: As base asset of that converter.\\n *\\n * ConverterNetwork:\\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\\n * and tokenAddressOut provided.\\n *\\n * findTokenConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\\n *\\n * findTokenConvertersForConverters():\\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\\n */\\n\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Maximum incentive could be\\n uint256 public constant MAX_INCENTIVE = 0.5e18;\\n\\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\\n uint256 public minAmountToConvert;\\n\\n /// @notice Venus price oracle contract\\n ResilientOracle public priceOracle;\\n\\n /// @notice conversion configurations for the existing pairs\\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\\n\\n /// @notice Address that all incoming tokens are transferred to\\n address public destinationAddress;\\n\\n /// @notice Boolean for if conversion is paused\\n bool public conversionPaused;\\n\\n /// @notice Address of the converterNetwork contract\\n IConverterNetwork public converterNetwork;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[45] private __gap;\\n\\n /// @notice Emitted when config is updated for tokens pair\\n event ConversionConfigUpdated(\\n address indexed tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 oldIncentive,\\n uint256 newIncentive,\\n ConversionAccessibility oldAccess,\\n ConversionAccessibility newAccess\\n );\\n /// @notice Emitted when price oracle address is updated\\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\\n\\n /// @notice Emitted when destination address is updated\\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\\n\\n /// @notice Emitted when converterNetwork address is updated\\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens\\n event ConvertedExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens\\n event ConvertedForExactTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n address indexed sender,\\n address indexed receiver,\\n address tokenAddressIn,\\n address indexed tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n );\\n\\n /// @notice Emitted when conversion is paused\\n event ConversionPaused(address indexed sender);\\n\\n /// @notice Emitted when conversion is unpaused\\n event ConversionResumed(address indexed sender);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Emitted when minimum amount to convert is updated\\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\\n\\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\\n error AmountOutMismatched();\\n\\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\\n error AmountInMismatched();\\n\\n /// @notice Thrown when given input amount is zero\\n error InsufficientInputAmount();\\n\\n /// @notice Thrown when given output amount is zero\\n error InsufficientOutputAmount();\\n\\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\\n error ConversionConfigNotEnabled();\\n\\n /// @notice Thrown when conversion is enabled only for private conversions\\n error ConversionEnabledOnlyForPrivateConversions();\\n\\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n error InvalidToAddress();\\n\\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\\n\\n /// @notice Thrown when amountOut is lower than amountOutMin\\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\\n\\n /// @notice Thrown when amountIn is higher than amountInMax\\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\\n\\n /// @notice Thrown when conversion is paused\\n error ConversionTokensPaused();\\n\\n /// @notice Thrown when conversion is Active\\n error ConversionTokensActive();\\n\\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\\n error InvalidTokenConfigAddresses();\\n\\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\\n error InsufficientPoolLiquidity();\\n\\n /// @notice When address of the ConverterNetwork is not set or Zero address\\n error InvalidConverterNetwork();\\n\\n /// @notice Thrown when trying to set non zero incentive for private conversion\\n error NonZeroIncentiveForPrivateConversion();\\n\\n /// @notice Thrown when using convertForExactTokens deflationary tokens\\n error DeflationaryTokenNotSupported();\\n\\n /// @notice Thrown when minimum amount to convert is zero\\n error InvalidMinimumAmountToConvert();\\n\\n /// @notice Thrown when there is a mismatch in the length of input arrays\\n error InputLengthMisMatch();\\n\\n /**\\n * @notice Modifier to ensure valid conversion parameters for a token conversion\\n * and check if conversion is paused or not\\n * @param to The recipient address for the converted tokens\\n * @param tokenAddressIn The input token address for the conversion\\n * @param tokenAddressOut The output token address for the conversion\\n */\\n modifier validConversionParameters(\\n address to,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) {\\n _checkConversionPaused();\\n ensureNonzeroAddress(to);\\n if (to == tokenAddressIn || to == tokenAddressOut) {\\n revert InvalidToAddress();\\n }\\n _;\\n }\\n\\n /// @notice Pause conversion of tokens\\n /// @custom:event Emits ConversionPaused on success\\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\\n /// @custom:access Restricted by ACM\\n function pauseConversion() external {\\n _checkAccessAllowed(\\\"pauseConversion()\\\");\\n _checkConversionPaused();\\n conversionPaused = true;\\n emit ConversionPaused(msg.sender);\\n }\\n\\n /// @notice Resume conversion of tokens.\\n /// @custom:event Emits ConversionResumed on success\\n /// @custom:error ConversionTokensActive thrown when conversion is already active\\n /// @custom:access Restricted by ACM\\n function resumeConversion() external {\\n _checkAccessAllowed(\\\"resumeConversion()\\\");\\n if (!conversionPaused) {\\n revert ConversionTokensActive();\\n }\\n\\n conversionPaused = false;\\n emit ConversionResumed(msg.sender);\\n }\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:access Only Governance\\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\\n _setPriceOracle(priceOracle_);\\n }\\n\\n /// @notice Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:access Only Governance\\n function setDestination(address destinationAddress_) external onlyOwner {\\n _setDestination(destinationAddress_);\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:access Only Governance\\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\\n _setConverterNetwork(converterNetwork_);\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:access Only Governance\\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\\n _checkAccessAllowed(\\\"setMinAmountToConvert(uint256)\\\");\\n _setMinAmountToConvert(minAmountToConvert_);\\n }\\n\\n /// @notice Batch sets the conversion configurations\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressesOut Array of addresses of tokenOut\\n /// @param conversionConfigs Array of conversionConfig config details to update\\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\\n function setConversionConfigs(\\n address tokenAddressIn,\\n address[] calldata tokenAddressesOut,\\n ConversionConfig[] calldata conversionConfigs\\n ) external {\\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\\n\\n for (uint256 i; i < tokenOutArrayLength; ) {\\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert AmountInMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\\n /// otherwise the amount is adjusted\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n if (actualAmountOut != amountOutMantissa) {\\n revert AmountOutMismatched();\\n }\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n }\\n\\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\\n amountInMantissa,\\n amountOutMinMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount transferred to destination\\n /// @return actualAmountOut Actual amount transferred to user\\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n )\\n external\\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\\n nonReentrant\\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\\n {\\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\\n amountInMaxMantissa,\\n amountOutMantissa,\\n tokenAddressIn,\\n tokenAddressOut,\\n to\\n );\\n\\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\\n msg.sender,\\n to,\\n tokenAddressIn,\\n tokenAddressOut,\\n actualAmountIn,\\n actualAmountOut\\n );\\n }\\n\\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\\n /// @param tokenAddress The address of the ERC-20 token to sweep\\n /// @param to The address to which tokens will be transferred\\n /// @param amount The amount to transfer\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n amountConvertedMantissa = amountInMantissa;\\n uint256 tokenInToOutConversion;\\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountConvertedMantissa = _divRoundingUp(maxTokenOutReserve * EXP_SCALE, tokenInToOutConversion);\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\\n /// @dev This function retrieves values without altering token prices\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n if (\\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountOutMantissa) {\\n amountOutMantissa = maxTokenOutReserve;\\n }\\n\\n amountConvertedMantissa = amountOutMantissa;\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountInMantissa;\\n }\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\\n priceOracle.updateAssetPrice(tokenAddressIn);\\n priceOracle.updateAssetPrice(tokenAddressOut);\\n\\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n amountConvertedMantissa = amountOutMantissa;\\n }\\n\\n /// @notice This method updated the states of this contract after getting funds from PSR\\n /// after settling the amount(if any) through privateConversion between converters\\n /// @dev This function is called by protocolShareReserve\\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\\n if (balanceDiff > 0) {\\n _privateConversion(comptroller, asset, balanceDiff);\\n }\\n }\\n\\n /// @notice Set the configuration for new or existing conversion pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n /// @custom:event Emits ConversionConfigUpdated event on success\\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\\n /// @custom:access Controlled by AccessControlManager\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) public {\\n _checkAccessAllowed(\\\"setConversionConfig(address,address,ConversionConfig)\\\");\\n ensureNonzeroAddress(tokenAddressIn);\\n ensureNonzeroAddress(tokenAddressOut);\\n\\n if (conversionConfig.incentive > MAX_INCENTIVE) {\\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\\n }\\n\\n if (\\n (tokenAddressIn == tokenAddressOut) ||\\n (tokenAddressIn != _getDestinationBaseAsset()) ||\\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\\n ) {\\n revert InvalidTokenConfigAddresses();\\n }\\n\\n if (\\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\\n conversionConfig.incentive != 0\\n ) {\\n revert NonZeroIncentiveForPrivateConversion();\\n }\\n\\n if (\\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\\n (address(converterNetwork) == address(0))\\n ) {\\n revert InvalidConverterNetwork();\\n }\\n\\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n emit ConversionConfigUpdated(\\n tokenAddressIn,\\n tokenAddressOut,\\n configuration.incentive,\\n conversionConfig.incentive,\\n configuration.conversionAccess,\\n conversionConfig.conversionAccess\\n );\\n\\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n } else {\\n configuration.incentive = conversionConfig.incentive;\\n configuration.conversionAccess = conversionConfig.conversionAccess;\\n }\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param token Address of the token\\n /// @param amount Amount transferred to address(to)\\n function preSweepToken(address token, uint256 amount) internal virtual {}\\n\\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\\n function _convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n if (amountOutMantissa < amountOutMinMantissa) {\\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\\n /// it is called by convertForExactTokens function\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n if (actualAmountIn != amountInMantissa) {\\n revert DeflationaryTokenNotSupported();\\n }\\n\\n if (actualAmountIn > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\\n actualAmountOut = amountOutMantissa;\\n }\\n\\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\\n function _convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\\n\\n if (amountInMantissa > amountInMaxMantissa) {\\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\\n }\\n\\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\\n\\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\\n\\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\\n }\\n\\n /// @dev return actualAmountOut from reserves for tokenAddressOut\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param to Address of the tokenAddressOut receiver\\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n function _doTransferOut(\\n address tokenAddressOut,\\n address to,\\n uint256 amountConvertedMantissa\\n ) internal {\\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\\n\\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\\n if (maxTokenOutReserve < amountConvertedMantissa) {\\n revert InsufficientPoolLiquidity();\\n }\\n\\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\\n\\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\\n tokenOut.safeTransfer(to, amountConvertedMantissa);\\n }\\n\\n /// @notice Transfer tokenAddressIn from user to destination\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @return actualAmountIn Actual amount transferred to destination\\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\\n }\\n\\n /// @dev Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n /// @custom:event Emits PriceOracleUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\\n ensureNonzeroAddress(address(priceOracle_));\\n emit PriceOracleUpdated(priceOracle, priceOracle_);\\n priceOracle = priceOracle_;\\n }\\n\\n /// @dev Sets a new destination address\\n /// @param destinationAddress_ The new destination address to be set\\n /// @custom:event Emits DestinationAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\\n function _setDestination(address destinationAddress_) internal {\\n ensureNonzeroAddress(destinationAddress_);\\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\\n destinationAddress = destinationAddress_;\\n }\\n\\n /// @notice Sets a converter network contract address\\n /// @param converterNetwork_ The converterNetwork address to be set\\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\\n ensureNonzeroAddress(address(converterNetwork_));\\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\\n converterNetwork = converterNetwork_;\\n }\\n\\n /// @notice Min amount to convert setter\\n /// @param minAmountToConvert_ Min amount to convert\\n /// @custom:event MinAmountToConvertUpdated is emitted in success\\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\\n ensureNonzeroValue(minAmountToConvert_);\\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\\n minAmountToConvert = minAmountToConvert_;\\n }\\n\\n /// @dev Hook to perform after converting tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @param amountIn Amount of tokenIn converted\\n /// @param amountOut Amount of tokenOut converted\\n function _postConversionHook(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n uint256 amountIn,\\n uint256 amountOut\\n ) internal virtual {}\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n __AccessControlled_init(accessControlManager_);\\n __ReentrancyGuard_init();\\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param minAmountToConvert_ minimum amount to convert\\n function __AbstractTokenConverter_init_unchained(\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n uint256 minAmountToConvert_\\n ) internal onlyInitializing {\\n _setPriceOracle(priceOracle_);\\n _setDestination(destinationAddress_);\\n _setMinAmountToConvert(minAmountToConvert_);\\n conversionPaused = false;\\n }\\n\\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address\\n /// @return Amount of asset, for _privateConversion\\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\\n\\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\\n /// destination contract as destination's base asset\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\\n function _privateConversion(\\n address comptroller,\\n address tokenAddressOut,\\n uint256 amountToConvert\\n ) internal {\\n address tokenAddressIn = _getDestinationBaseAsset();\\n address _destinationAddress = destinationAddress;\\n uint256 convertedTokenInBalance;\\n if (address(converterNetwork) != address(0)) {\\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\\n uint256 convertersLength = converterAddresses.length;\\n for (uint256 i; i < convertersLength; ) {\\n if (converterBalances[i] == 0) break;\\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\\n converterBalances[i],\\n tokenAddressOut,\\n tokenAddressIn\\n );\\n if (amountIn > amountToConvert) {\\n amountIn = amountToConvert;\\n }\\n\\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\\n break;\\n }\\n\\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n\\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\\n amountIn,\\n 0,\\n tokenAddressOut,\\n tokenAddressIn,\\n _destinationAddress\\n );\\n\\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\\n amountToConvert -= amountIn;\\n convertedTokenInBalance += (balanceAfter - balanceBefore);\\n\\n if (amountToConvert == 0) break;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n _postPrivateConversionHook(\\n comptroller,\\n tokenAddressIn,\\n convertedTokenInBalance,\\n tokenAddressOut,\\n amountToConvert\\n );\\n }\\n\\n /// @dev This hook is used to update states for the converter after the privateConversion\\n /// @param comptroller Comptroller address (pool)\\n /// @param tokenAddressIn Address of the destination's base asset\\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\\n function _postPrivateConversionHook(\\n address comptroller,\\n address tokenAddressIn,\\n uint256 convertedTokenInBalance,\\n address tokenAddressOut,\\n uint256 convertedTokenOutBalance\\n ) internal virtual {}\\n\\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\\n /// @param tokenOutAddress Address of the asset to be transferred to the user\\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\\n\\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\\n /// @param amountIn The amount to convert\\n /// @param tokenAddress Address of the token\\n /// @return isValid true if amount to convert is greater than minimum amount to convert\\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\\n priceOracle.updateAssetPrice(tokenAddress);\\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\\n\\n if (amountInInUsd >= minAmountToConvert) {\\n isValid = true;\\n }\\n }\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\\n if (amountInMantissa == 0) {\\n revert InsufficientInputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\\n /// multiplied by conversionWithIncentive which will be >= 1\\n amountOutMantissa = (amountInMantissa * tokenInToOutConversion) / (EXP_SCALE);\\n }\\n\\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function _getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\\n if (amountOutMantissa == 0) {\\n revert InsufficientOutputAmount();\\n }\\n\\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\\n\\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\\n revert ConversionConfigNotEnabled();\\n }\\n\\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\\n\\n uint256 incentive = configuration.incentive;\\n\\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\\n converterNetwork.isTokenConverter(msg.sender);\\n if (isPrivateConversion) {\\n incentive = 0;\\n }\\n\\n /// conversion rate after considering incentive(conversionWithIncentive)\\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\\n\\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\\n if (isPrivateConversion) {\\n amountInMantissa =\\n (amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) /\\n (tokenInUnderlyingPrice * conversionWithIncentive);\\n } else {\\n amountInMantissa = _divRoundingUp(\\n amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE,\\n tokenInUnderlyingPrice * conversionWithIncentive\\n );\\n }\\n\\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\\n }\\n\\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\\n if (\\n (!(isConverter) &&\\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\\n ) {\\n revert ConversionEnabledOnlyForPrivateConversions();\\n }\\n }\\n\\n /// @dev To check, is conversion paused\\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\\n function _checkConversionPaused() internal view {\\n if (conversionPaused) {\\n revert ConversionTokensPaused();\\n }\\n }\\n\\n /// @dev Get base asset address of the destination contract\\n /// @return Address of the base asset\\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\\n\\n /// @dev Performs division where the result is rounded up\\n /// @param numerator The numerator of the division operation\\n /// @param denominator The denominator of the division operation. Must be non-zero\\n /// @return The result of the division, rounded up\\n function _divRoundingUp(uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return (numerator + denominator - 1) / denominator;\\n }\\n}\\n\",\"keccak256\":\"0x3a55b64cf2b9fe6872bffa9eabfbeef0a836227a0e8b588d813ae856771a40e9\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/IAbstractTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { IConverterNetwork } from \\\"../Interfaces/IConverterNetwork.sol\\\";\\n\\n/// @notice Interface for AbstractTokenConverter\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ninterface IAbstractTokenConverter {\\n /// @notice This enum define the all possible ways of conversion can happen\\n enum ConversionAccessibility {\\n NONE, // Conversion is disable for the pair\\n ALL, // Conversion is enable for private conversion and users\\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\\n ONLY_FOR_USERS // Conversion is enable only for users\\n }\\n\\n /// @notice This struct represents the configuration for a token conversion.\\n struct ConversionConfig {\\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\\n uint256 incentive;\\n /// enable or disable conversion for users or converters or both or none\\n ConversionAccessibility conversionAccess;\\n }\\n\\n /// @notice Pause conversion of tokens\\n function pauseConversion() external;\\n\\n /// @notice Resume conversion of tokens.\\n function resumeConversion() external;\\n\\n /// @notice Sets a new price oracle\\n /// @param priceOracle_ Address of the new price oracle to set\\n function setPriceOracle(ResilientOracle priceOracle_) external;\\n\\n /// @notice Set the configuration for new or existing convert pair\\n /// @param tokenAddressIn Address of tokenIn\\n /// @param tokenAddressOut Address of tokenOut\\n /// @param conversionConfig ConversionConfig config details to update\\n function setConversionConfig(\\n address tokenAddressIn,\\n address tokenAddressOut,\\n ConversionConfig calldata conversionConfig\\n ) external;\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @dev Method does not support deflationary tokens transfer\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMantissa,\\n uint256 amountOutMinMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after convert\\n /// @param to Address of the tokenAddressOut receiver\\n function convertForExactTokensSupportingFeeOnTransferTokens(\\n uint256 amountInMaxMantissa,\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut,\\n address to\\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\\n\\n /// @notice Get the configuration for the pair of the tokens\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\\n /// @return conversionAccess Accessibility for the pair of tokens\\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\\n external\\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\\n\\n /// @notice Get the address of the converterNetwork\\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getUpdatedAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountIn(\\n uint256 amountOutMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\\n\\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\\n /// @dev This function retrieves values without altering token prices.\\n /// @param amountInMantissa Amount of tokenAddressIn\\n /// @param tokenAddressIn Address of the token to convert\\n /// @param tokenAddressOut Address of the token to get after conversion\\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\\n function getAmountOut(\\n uint256 amountInMantissa,\\n address tokenAddressIn,\\n address tokenAddressOut\\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\\n\\n /// @notice Get the balance for specific token\\n /// @param token Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address token) external view returns (uint256 tokenBalance);\\n}\\n\",\"keccak256\":\"0xc677c12e2f04e520fb1fa02a1f06ad37d821cfebb5aa8f4bd7a22410648a0aae\",\"license\":\"BSD-3-Clause\"},\"contracts/TokenConverter/SingleTokenConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { ResilientOracle } from \\\"@venusprotocol/oracle/contracts/ResilientOracle.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { AbstractTokenConverter } from \\\"./AbstractTokenConverter.sol\\\";\\n\\n/// @title SingleTokenConverter\\n/// @author Venus\\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract SingleTokenConverter is AbstractTokenConverter {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Address of the base asset token\\n address public baseAsset;\\n\\n /// @notice Emitted when base asset is updated\\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\\n\\n /// @notice Emmitted after the funds transferred to the destination address\\n event AssetTransferredToDestination(\\n address indexed receiver,\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /// @param accessControlManager_ Access control manager contract address\\n /// @param priceOracle_ Resilient oracle address\\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\\n /// @param baseAsset_ Address of the base asset\\n /// @param minAmountToConvert_ Minimum amount to convert\\n function initialize(\\n address accessControlManager_,\\n ResilientOracle priceOracle_,\\n address destinationAddress_,\\n address baseAsset_,\\n uint256 minAmountToConvert_\\n ) public initializer {\\n _setBaseAsset(baseAsset_);\\n\\n // Initialize AbstractTokenConverter\\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\\n }\\n\\n /// @notice Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:access Only Governance\\n function setBaseAsset(address baseAsset_) external onlyOwner {\\n _setBaseAsset(baseAsset_);\\n }\\n\\n /// @notice Get the balance for specific token\\n /// @param tokenAddress Address of the token\\n /// @return tokenBalance Balance of the token the contract has\\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n tokenBalance = token.balanceOf(address(this));\\n }\\n\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Asset address.\\n /// @return balanceLeft Amount of asset, for _privateConversion\\n // solhint-disable-next-line\\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\\n IERC20Upgradeable token = IERC20Upgradeable(asset);\\n uint256 balance = token.balanceOf(address(this));\\n balanceLeft = balance;\\n\\n if (asset == baseAsset) {\\n balanceLeft = 0;\\n token.safeTransfer(destinationAddress, balance);\\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\\n }\\n }\\n\\n /// @dev Sets the base asset for the contract\\n /// @param baseAsset_ The new address of the base asset\\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\\n /// @custom:event BaseAssetUpdated is emitted on success\\n function _setBaseAsset(address baseAsset_) internal {\\n ensureNonzeroAddress(baseAsset_);\\n emit BaseAssetUpdated(baseAsset, baseAsset_);\\n baseAsset = baseAsset_;\\n }\\n\\n /// @dev Get base asset address\\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\\n destinationBaseAsset = baseAsset;\\n }\\n}\\n\",\"keccak256\":\"0x385804c4f8a1d5b0ed58da01f584c778e2a869b280ad6cb607b7fe8539c51897\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6140c480620000f36000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d436600461383a565b610562565b005b6102ee6102e9366004613857565b610576565b60408051928352602083019190915201610288565b6102d961031136600461383a565b610624565b60fc54610274906001600160a01b031681565b6102d961033736600461383a565b610635565b6102ee61034a366004613899565b610646565b6102d961035d36600461383a565b610784565b6102d961037036600461383a565b610795565b6102d96107a6565b6102ee61038b366004613857565b61088c565b6102d961039e3660046138f8565b61095a565b6102ee6103b1366004613857565b6109f7565b6102ee6103c4366004613857565b610b00565b6103dc6103d736600461383a565b610bff565b604051908152602001610288565b6102d9610c8c565b6102d9610400366004613939565b610ca0565b6102d9610ce7565b6033546001600160a01b0316610274565b6102ee61042c366004613899565b610d77565b6102d961043f366004613952565b610e61565b610479610452366004613952565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139f5565b6097546001600160a01b0316610274565b6102ee6104a6366004613899565b610e97565b6102d9610f81565b6102d96104c1366004613a55565b611033565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613899565b6110d1565b6102d961052e366004613b09565b6111f4565b6102d961054136600461383a565b611593565b6102d9610554366004613b7a565b61161c565b6103dc60fb5481565b61056a6117a6565b61057381611800565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b861398b565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610bff565b905085811015610608578095505b85925061061686868661187d565b508092505050935093915050565b61062c6117a6565b61057381611be3565b61063d6117a6565b61057381611cd8565b600080828585610654611d57565b61065d83611dac565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611dec565b6106da8a8a8a8a8a611e45565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117a6565b61057381611ecc565b61079d6117a6565b61057381611f49565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611fc6565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce61398b565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610915868686612092565b9092509050600061092585610bff565b9050828110156109505761094a610944670de0b6b3a764000083613c0d565b8361239f565b93508092505b5050935093915050565b6109626117a6565b61096a611dec565b61097383611dac565b61097c82611dac565b610985816123c2565b8261099a6001600160a01b03821684846123fc565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109df91815260200190565b60405180910390a3506109f2600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a5b57600080fd5b505af1158015610a6f573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610ad357600080fd5b505af1158015610ae7573d6000803e3d6000fd5b50505050610af6858585612092565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b6457600080fd5b505af1158015610b78573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bdc57600080fd5b505af1158015610bf0573d6000803e3d6000fd5b50505050610af685858561187d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c859190613c4a565b9392505050565b610c946117a6565b610c9e60006124c3565b565b610cde6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611fc6565b610573816124f4565b60655433906001600160a01b03168114610d6e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610573816124c3565b600080828585610d85611d57565b610d8e83611dac565b816001600160a01b0316836001600160a01b03161480610dbf5750806001600160a01b0316836001600160a01b0316145b15610df6576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfe611dec565b610e0b8a8a8a8a8a611e45565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e69611dec565b6000610e75838361253e565b90508015610e8857610e88838383612653565b50610e93600160c955565b5050565b600080828585610ea5611d57565b610eae83611dac565b816001600160a01b0316836001600160a01b03161480610edf5750806001600160a01b0316836001600160a01b0316145b15610f16576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1e611dec565b610f2b8a8a8a8a8a612b10565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fbf6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611fc6565b610fc7611d57565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b8281811461106d576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110c8576110c08787878481811061108e5761108e613c63565b90506020020160208101906110a3919061383a565b8686858181106110b5576110b5613c63565b9050604002016111f4565b600101611070565b50505050505050565b6000808285856110df611d57565b6110e883611dac565b816001600160a01b0316836001600160a01b031614806111195750806001600160a01b0316836001600160a01b0316145b15611150576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611158611dec565b6111658a8a8a8a8a612ba2565b90955093508884146111a3576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61121560405180606001604052806035815260200161405a60359139611fc6565b61121e83611dac565b61122782611dac565b6706f05b59d3b200008135111561127b576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d65565b816001600160a01b0316836001600160a01b031614806112aa575061012d546001600160a01b03848116911614155b806112f2575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff1660038111156112ef576112ef61398b565b14155b15611329576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261133b6040830160208401613c92565b600381111561134c5761134c61398b565b1480156113595750803515155b15611390576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113a26040830160208401613c92565b60038111156113b3576113b361398b565b14806113df575060016113cc6040830160208401613c92565b60038111156113dd576113dd61398b565b145b80156113f4575060ff546001600160a01b0316155b1561142b576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff9091169161149b91908a01908a01613c92565b6040516114ab9493929190613cb3565b60405180910390a360006114c56040840160208501613c92565b60038111156114d6576114d661398b565b03611533576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905561158d565b813581556115476040830160208401613c92565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115875761158761398b565b02179055505b50505050565b61159b6117a6565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115e46033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff161580801561163c5750600054600160ff909116105b806116565750303b158015611656575060005460ff166001145b6116c85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d65565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561172657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61172f83611cd8565b61173b86868685612c5f565b801561179e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610c9e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d65565b61180981611dac565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118ba576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561190e5761190e61398b565b600381111561191f5761191f61398b565b905250905060008160200151600381111561193c5761193c61398b565b03611973576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fb9190613c4a565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a889190613c4a565b835160ff54919250906000906001600160a01b031615801590611b2b575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2b9190613ce4565b90508015611b3857600091505b6000611b4c83670de0b6b3a7640000613d06565b90508115611b8c57611b5e8186613c0d565b670de0b6b3a7640000611b71868e613c0d565b611b7b9190613c0d565b611b859190613d1e565b9750611bbe565b611bbb670de0b6b3a7640000611ba2868e613c0d565b611bac9190613c0d565b611bb68388613c0d565b61239f565b97505b83611bc98287613c0d565b611bd39190613d1e565b9650505050505050935093915050565b6001600160a01b038116611c5f5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d65565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611ce181611dac565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610c9e576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e3e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d65565b600260c955565b600080611e528585612cf8565b611e5c8588612e18565b9150611e698286866109f7565b91505085811015611eb0576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d65565b611ebb848483612f63565b9550959350505050565b600160c955565b611ed581611dac565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f5281611dac565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906120129033908690600401613dcf565b602060405180830381865afa15801561202f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120539190613ce4565b905080610e93573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d6593929190613df1565b600080846000036120cf576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff1660038111156121235761212361398b565b60038111156121345761213461398b565b90525090506000816020015160038111156121515761215161398b565b03612188576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122109190613c4a565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612279573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229d9190613c4a565b835160ff54919250906001600160a01b03161580159061233d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061233d9190613ce4565b15612346575060005b600061235a82670de0b6b3a7640000613d06565b9050826123678286613c0d565b6123719190613d1e565b9550670de0b6b3a7640000612386878c613c0d565b6123909190613d1e565b96505050505050935093915050565b60008160016123ae8286613d06565b6123b89190613e1d565b610c859190613d1e565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b0383166024820152604481018290526109f29084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612fc6565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610573816130ae565b6124fd816123c2565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa1580156125a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c69190613c4a565b61012d549093508391506001600160a01b039081169085160361264b5760fe5460009350612601906001600160a01b038481169116836123fc565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061266861012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612b0b5760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261273d9190810190613f41565b8151919350915060005b81811015612b065782818151811061276157612761613c63565b602002602001015160000315612b0657600084828151811061278557612785613c63565b60200260200101516001600160a01b0316636f1a30a88584815181106127ad576127ad613c63565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127ef939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af115801561280d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128319190614006565b9150508881111561283f5750875b612849818b613118565b6128535750612b06565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa1580156128b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128da9190613c4a565b90508a6001600160a01b031663095ea7b38785815181106128fd576128fd613c63565b6020026020010151846040518363ffffffff1660e01b81526004016129379291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015612956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297a9190613ce4565b5085838151811061298d5761298d613c63565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015612a17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a3b9190614006565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac49190613c4a565b9050612ad0838c613e1d565b9a50612adc8282613e1d565b612ae69089613d06565b97508a600003612af857505050612b06565b836001019350505050612747565b505050505b61179e565b600080612b1d8585612cf8565b6000612b2a878787610b00565b91505087811115612b71576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d65565b612b7b8682612e18565b9250612b888387876109f7565b9250612b979050858584612f63565b509550959350505050565b600080612baf8585612cf8565b6000612bbc878787610b00565b915050612bc98682612e18565b9250808314612c04576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c48576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d65565b612c53858589612f63565b50909694955050505050565b600054610100900460ff16612cdc5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b612ce584613250565b612ced6132de565b61158d838383613363565b60ff546000906001600160a01b031615801590612d95575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d959190613ce4565b905080158015612de1575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612ddf57612ddf61398b565b145b156109f2576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea59190613c4a565b60fe54909150612ec4906001600160a01b038481169133911687613428565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612f29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f4d9190613c4a565b9050612f598282613e1d565b9695505050505050565b6000612f6e84610bff565b905081811015612faa576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612fbf6001600160a01b03821685856123fc565b5050505050565b600061301b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134799092919063ffffffff16565b905080516000148061303c57508080602001905181019061303c9190613ce4565b6109f25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d65565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561317957600080fd5b505af115801561318d573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa158015613201573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132259190613c4a565b61322f9190613c0d565b6132399190613d1e565b905060fb54811061324957600191505b5092915050565b600054610100900460ff166132cd5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6132d5613490565b61057381613515565b600054610100900460ff1661335b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e613592565b600054610100900460ff166133e05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6133e983611f49565b6133f282611800565b6133fb816124f4565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b038085166024830152831660448201526064810182905261158d9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612441565b6060613488848460008561360f565b949350505050565b600054610100900460ff1661350d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e613701565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b600054610100900460ff16611ec55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6060824710156136875760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d65565b600080866001600160a01b031685876040516136a3919061402a565b60006040518083038185875af1925050503d80600081146136e0576040519150601f19603f3d011682016040523d82523d6000602084013e6136e5565b606091505b50915091506136f687838387613787565b979650505050505050565b600054610100900460ff1661377e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e336124c3565b606083156137f65782516000036137ef576001600160a01b0385163b6137ef5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d65565b5081613488565b613488838381511561380b5781518083602001fd5b8060405162461bcd60e51b8152600401610d659190614046565b6001600160a01b038116811461057357600080fd5b60006020828403121561384c57600080fd5b8135610c8581613825565b60008060006060848603121561386c57600080fd5b83359250602084013561387e81613825565b9150604084013561388e81613825565b809150509250925092565b600080600080600060a086880312156138b157600080fd5b853594506020860135935060408601356138ca81613825565b925060608601356138da81613825565b915060808601356138ea81613825565b809150509295509295909350565b60008060006060848603121561390d57600080fd5b833561391881613825565b9250602084013561392881613825565b929592945050506040919091013590565b60006020828403121561394b57600080fd5b5035919050565b6000806040838503121561396557600080fd5b823561397081613825565b9150602083013561398081613825565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139f1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c8560208301846139ba565b60008083601f840112613a1b57600080fd5b50813567ffffffffffffffff811115613a3357600080fd5b6020830191508360208260061b8501011115613a4e57600080fd5b9250929050565b600080600080600060608688031215613a6d57600080fd5b8535613a7881613825565b9450602086013567ffffffffffffffff80821115613a9557600080fd5b818801915088601f830112613aa957600080fd5b813581811115613ab857600080fd5b8960208260051b8501011115613acd57600080fd5b602083019650809550506040880135915080821115613aeb57600080fd5b50613af888828901613a09565b969995985093965092949392505050565b60008060008385036080811215613b1f57600080fd5b8435613b2a81613825565b93506020850135613b3a81613825565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b6c57600080fd5b506040840190509250925092565b600080600080600060a08688031215613b9257600080fd5b8535613b9d81613825565b94506020860135613bad81613825565b93506040860135613bbd81613825565b92506060860135613bcd81613825565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c4557613c45613bde565b500290565b600060208284031215613c5c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613ca457600080fd5b813560048110610c8557600080fd5b8481526020810184905260808101613cce60408301856139ba565b613cdb60608301846139ba565b95945050505050565b600060208284031215613cf657600080fd5b81518015158114610c8557600080fd5b60008219821115613d1957613d19613bde565b500190565b600082613d54577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613d74578181015183820152602001613d5c565b8381111561158d5750506000910152565b60008151808452613d9d816020860160208601613d59565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134886040830184613d85565b60006001600160a01b03808616835280851660208401525060606040830152613cdb6060830184613d85565b600082821015613e2f57613e2f613bde565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613eaa57613eaa613e34565b604052919050565b600067ffffffffffffffff821115613ecc57613ecc613e34565b5060051b60200190565b600082601f830112613ee757600080fd5b81516020613efc613ef783613eb2565b613e63565b82815260059290921b84018101918181019086841115613f1b57600080fd5b8286015b84811015613f365780518352918301918301613f1f565b509695505050505050565b60008060408385031215613f5457600080fd5b825167ffffffffffffffff80821115613f6c57600080fd5b818501915085601f830112613f8057600080fd5b81516020613f90613ef783613eb2565b82815260059290921b84018101918181019089841115613faf57600080fd5b948201945b83861015613fd6578551613fc781613825565b82529482019490820190613fb4565b91880151919650909350505080821115613fef57600080fd5b50613ffc85828601613ed6565b9150509250929050565b6000806040838503121561401957600080fd5b505080516020909101519092909150565b6000825161403c818460208701613d59565b9190910192915050565b602081526000610c856020830184613d8556fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220c90768b57d16a90270136f659c9003d1890ce1f6dcc427a5e56b6e83cfbf87c164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061025c5760003560e01c806379ba509711610145578063ca325469116100bd578063f04c31871161008c578063f2fde38b11610071578063f2fde38b14610533578063f7013ef614610546578063fe3da9841461055957600080fd5b8063f04c31871461050d578063f0dc7e9d1461052057600080fd5b8063ca325469146104c6578063cdf456e1146104d9578063e2ff7ea2146104ed578063e30c3978146104fc57600080fd5b8063b491ddf711610114578063b6828c57116100f9578063b6828c5714610498578063bc368b04146104ab578063c0654646146104b357600080fd5b8063b491ddf714610444578063b4a0bdf31461048757600080fd5b806379ba5097146104055780638da5cb5b1461040d57806390fa7b541461041e578063aac59a751461043157600080fd5b8063530e784f116101d85780636daa463b116101a757806370a082311161018c57806370a08231146103c9578063715018a6146103ea578063746460a9146103f257600080fd5b80636daa463b146103a35780636f1a30a8146103b657600080fd5b8063530e784f1461036257806358b904df146103755780635e1e63251461037d57806364aff9ec1461039057600080fd5b80630e32cb861161022f5780633606b26c116102145780633606b26c14610329578063439727a51461033c57806352e21a181461034f57600080fd5b80630e32cb86146103035780632630c12f1461031657600080fd5b806301e201781461026157806307aa239e146102915780630a0a05e6146102c65780630a9a2b72146102db575b600080fd5b60ff54610274906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fe546102b69074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610288565b6102d96102d436600461383a565b610562565b005b6102ee6102e9366004613857565b610576565b60408051928352602083019190915201610288565b6102d961031136600461383a565b610624565b60fc54610274906001600160a01b031681565b6102d961033736600461383a565b610635565b6102ee61034a366004613899565b610646565b6102d961035d36600461383a565b610784565b6102d961037036600461383a565b610795565b6102d96107a6565b6102ee61038b366004613857565b61088c565b6102d961039e3660046138f8565b61095a565b6102ee6103b1366004613857565b6109f7565b6102ee6103c4366004613857565b610b00565b6103dc6103d736600461383a565b610bff565b604051908152602001610288565b6102d9610c8c565b6102d9610400366004613939565b610ca0565b6102d9610ce7565b6033546001600160a01b0316610274565b6102ee61042c366004613899565b610d77565b6102d961043f366004613952565b610e61565b610479610452366004613952565b60fd6020908152600092835260408084209091529082529020805460019091015460ff1682565b6040516102889291906139f5565b6097546001600160a01b0316610274565b6102ee6104a6366004613899565b610e97565b6102d9610f81565b6102d96104c1366004613a55565b611033565b60fe54610274906001600160a01b031681565b61012d54610274906001600160a01b031681565b6103dc6706f05b59d3b2000081565b6065546001600160a01b0316610274565b6102ee61051b366004613899565b6110d1565b6102d961052e366004613b09565b6111f4565b6102d961054136600461383a565b611593565b6102d9610554366004613b7a565b61161c565b6103dc60fb5481565b61056a6117a6565b61057381611800565b50565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156105b8576105b861398b565b036105ef576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105fa84610bff565b905085811015610608578095505b85925061061686868661187d565b508092505050935093915050565b61062c6117a6565b61057381611be3565b61063d6117a6565b61057381611cd8565b600080828585610654611d57565b61065d83611dac565b816001600160a01b0316836001600160a01b0316148061068e5750806001600160a01b0316836001600160a01b0316145b156106c5576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106cd611dec565b6106da8a8a8a8a8a611e45565b9095509350898514610718576040517fc214279600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f795a235be939acb902ac69562805f86e1341a9b019c351b996e2aa2dfc34c67c906060015b60405180910390a4610777600160c955565b5050509550959350505050565b61078c6117a6565b61057381611ecc565b61079d6117a6565b61057381611f49565b6107e46040518060400160405280601281526020017f726573756d65436f6e76657273696f6e28290000000000000000000000000000815250611fc6565b60fe5474010000000000000000000000000000000000000000900460ff16610837576040517e6d8dbb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905560405133907f89b79206f08dadd78502cff5075d2b094fa0abea0b063cfafe4475e2a380c51f90600090a2565b60008060026001600160a01b03808616600090815260fd602090815260408083209388168352929052206001015460ff1660038111156108ce576108ce61398b565b03610905576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8491506000610915868686612092565b9092509050600061092585610bff565b9050828110156109505761094a610944670de0b6b3a764000083613c0d565b8361239f565b93508092505b5050935093915050565b6109626117a6565b61096a611dec565b61097383611dac565b61097c82611dac565b610985816123c2565b8261099a6001600160a01b03821684846123fc565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516109df91815260200190565b60405180910390a3506109f2600160c955565b505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610a5b57600080fd5b505af1158015610a6f573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610ad357600080fd5b505af1158015610ae7573d6000803e3d6000fd5b50505050610af6858585612092565b5094959350505050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152600092839291169063b62cad6990602401600060405180830381600087803b158015610b6457600080fd5b505af1158015610b78573d6000803e3d6000fd5b505060fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152909116925063b62cad699150602401600060405180830381600087803b158015610bdc57600080fd5b505af1158015610bf0573d6000803e3d6000fd5b50505050610af685858561187d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009082906001600160a01b038216906370a0823190602401602060405180830381865afa158015610c61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c859190613c4a565b9392505050565b610c946117a6565b610c9e60006124c3565b565b610cde6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611fc6565b610573816124f4565b60655433906001600160a01b03168114610d6e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610573816124c3565b600080828585610d85611d57565b610d8e83611dac565b816001600160a01b0316836001600160a01b03161480610dbf5750806001600160a01b0316836001600160a01b0316145b15610df6576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfe611dec565b610e0b8a8a8a8a8a611e45565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f93b7ba2a2b0e36320375853d7466af5685c07567804b871b4fdfd31e3bb7715490606001610765565b610e69611dec565b6000610e75838361253e565b90508015610e8857610e88838383612653565b50610e93600160c955565b5050565b600080828585610ea5611d57565b610eae83611dac565b816001600160a01b0316836001600160a01b03161480610edf5750806001600160a01b0316836001600160a01b0316145b15610f16576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1e611dec565b610f2b8a8a8a8a8a612b10565b9095509350604080516001600160a01b038a81168252602082018890529181018690528189169188169033907f9b7dc1d7d2974d015b4fc39889a09f3a3923add808f5863158f3162d997d4e8290606001610765565b610fbf6040518060400160405280601181526020017f7061757365436f6e76657273696f6e2829000000000000000000000000000000815250611fc6565b610fc7611d57565b60fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560405133907f490bc639fd0d96f19c8adf77bc98d17fbefdee2e1e1864d21f041360d0ee065a90600090a2565b8281811461106d576040517f4d5590f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156110c8576110c08787878481811061108e5761108e613c63565b90506020020160208101906110a3919061383a565b8686858181106110b5576110b5613c63565b9050604002016111f4565b600101611070565b50505050505050565b6000808285856110df611d57565b6110e883611dac565b816001600160a01b0316836001600160a01b031614806111195750806001600160a01b0316836001600160a01b0316145b15611150576040517f8aa3a72f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611158611dec565b6111658a8a8a8a8a612ba2565b90955093508884146111a3576040517fa8dc653c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038a81168252602082018890529181018690528189169188169033907fcb4ea7de8d069b0f443b792cba6c6df5096508951bbc75c04ac42c9251efe07690606001610765565b61121560405180606001604052806035815260200161405a60359139611fc6565b61121e83611dac565b61122782611dac565b6706f05b59d3b200008135111561127b576040517f9770caee000000000000000000000000000000000000000000000000000000008152813560048201526706f05b59d3b200006024820152604401610d65565b816001600160a01b0316836001600160a01b031614806112aa575061012d546001600160a01b03848116911614155b806112f2575060006001600160a01b03808416600090815260fd602090815260408083209388168352929052206001015460ff1660038111156112ef576112ef61398b565b14155b15611329576040517feebb5ac600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600261133b6040830160208401613c92565b600381111561134c5761134c61398b565b1480156113595750803515155b15611390576040517fd0d4aabe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026113a26040830160208401613c92565b60038111156113b3576113b361398b565b14806113df575060016113cc6040830160208401613c92565b60038111156113dd576113dd61398b565b145b80156113f4575060ff546001600160a01b0316155b1561142b576040517fe7c2c99400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600081815260fd602090815260408083209487168084529482529182902080546001820154919594937f39fbfdd5da133303ed31b1b65e30a0ddf7a9236573368c66c859dceccc1dd12a93919288359260ff9091169161149b91908a01908a01613c92565b6040516114ab9493929190613cb3565b60405180910390a360006114c56040840160208501613c92565b60038111156114d6576114d661398b565b03611533576001600160a01b03808516600090815260fd60209081526040808320938716835292905290812090815560010180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905561158d565b813581556115476040830160208401613c92565b6001808301805490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156115875761158761398b565b02179055505b50505050565b61159b6117a6565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556115e46033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff161580801561163c5750600054600160ff909116105b806116565750303b158015611656575060005460ff166001145b6116c85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d65565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561172657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61172f83611cd8565b61173b86868685612c5f565b801561179e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6033546001600160a01b03163314610c9e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d65565b61180981611dac565b60fe546040516001600160a01b038084169216907f9be3097b5c8b276786be52a244ee90d66efd34805d9eb16f168fb2b4aaae9a2b90600090a360fe80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080846000036118ba576040517f42301c2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff16600381111561190e5761190e61398b565b600381111561191f5761191f61398b565b905250905060008160200151600381111561193c5761193c61398b565b03611973576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156119d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fb9190613c4a565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015611a64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a889190613c4a565b835160ff54919250906000906001600160a01b031615801590611b2b575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015611b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2b9190613ce4565b90508015611b3857600091505b6000611b4c83670de0b6b3a7640000613d06565b90508115611b8c57611b5e8186613c0d565b670de0b6b3a7640000611b71868e613c0d565b611b7b9190613c0d565b611b859190613d1e565b9750611bbe565b611bbb670de0b6b3a7640000611ba2868e613c0d565b611bac9190613c0d565b611bb68388613c0d565b61239f565b97505b83611bc98287613c0d565b611bd39190613d1e565b9650505050505050935093915050565b6001600160a01b038116611c5f5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610d65565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b611ce181611dac565b61012d546040516001600160a01b038084169216907f4fe44995ca2482562846e3c0413d9bd6147e9ce1881c66a8765e8542fef99f4290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60fe5474010000000000000000000000000000000000000000900460ff1615610c9e576040517f952bcf7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116610573576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260c95403611e3e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d65565b600260c955565b600080611e528585612cf8565b611e5c8588612e18565b9150611e698286866109f7565b91505085811015611eb0576040517f228f8c110000000000000000000000000000000000000000000000000000000081526004810182905260248101879052604401610d65565b611ebb848483612f63565b9550959350505050565b600160c955565b611ed581611dac565b60ff546040516001600160a01b038084169216907f50f1a16bf24734355b14ff800d132cc0a934808b8621d5623b41bc67f204881790600090a360ff80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611f5281611dac565b60fc546040516001600160a01b038084169216907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a360fc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906120129033908690600401613dcf565b602060405180830381865afa15801561202f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120539190613ce4565b905080610e93573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610d6593929190613df1565b600080846000036120cf576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808516600090815260fd6020908152604080832093871683529281528282208351808501909452805484526001810154929392909183019060ff1660038111156121235761212361398b565b60038111156121345761213461398b565b90525090506000816020015160038111156121515761215161398b565b03612188576040517f618ce59700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009216906341976e0990602401602060405180830381865afa1580156121ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122109190613c4a565b60fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152929350600092909116906341976e0990602401602060405180830381865afa158015612279573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229d9190613c4a565b835160ff54919250906001600160a01b03161580159061233d575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061233d9190613ce4565b15612346575060005b600061235a82670de0b6b3a7640000613d06565b9050826123678286613c0d565b6123719190613d1e565b9550670de0b6b3a7640000612386878c613c0d565b6123909190613d1e565b96505050505050935093915050565b60008160016123ae8286613d06565b6123b89190613e1d565b610c859190613d1e565b80600003610573576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b0383166024820152604481018290526109f29084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612fc6565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610573816130ae565b6124fd816123c2565b60fb5460408051918252602082018390527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d910160405180910390a160fb55565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090829082906001600160a01b038316906370a0823190602401602060405180830381865afa1580156125a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c69190613c4a565b61012d549093508391506001600160a01b039081169085160361264b5760fe5460009350612601906001600160a01b038481169116836123fc565b60fe546040518281526001600160a01b0386811692888216929116907fadc20ad416881f76b4304665c35f5be8592297bcdfe4f0bb087b9d254222af559060200160405180910390a45b505092915050565b600061266861012d546001600160a01b031690565b60fe5460ff549192506001600160a01b03908116916000911615612b0b5760ff546040517f4e9f8f390000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285811660248301526000928392911690634e9f8f39906044016000604051808303816000875af11580156126f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261273d9190810190613f41565b8151919350915060005b81811015612b065782818151811061276157612761613c63565b602002602001015160000315612b0657600084828151811061278557612785613c63565b60200260200101516001600160a01b0316636f1a30a88584815181106127ad576127ad613c63565b60200260200101518c8b6040518463ffffffff1660e01b81526004016127ef939291909283526001600160a01b03918216602084015216604082015260600190565b60408051808303816000875af115801561280d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128319190614006565b9150508881111561283f5750875b612849818b613118565b6128535750612b06565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152600091908a16906370a0823190602401602060405180830381865afa1580156128b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128da9190613c4a565b90508a6001600160a01b031663095ea7b38785815181106128fd576128fd613c63565b6020026020010151846040518363ffffffff1660e01b81526004016129379291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015612956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297a9190613ce4565b5085838151811061298d5761298d613c63565b60209081029190910101516040517f439727a500000000000000000000000000000000000000000000000000000000815260048101849052600060248201526001600160a01b038d811660448301528b811660648301528a811660848301529091169063439727a59060a40160408051808303816000875af1158015612a17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a3b9190614006565b50506040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152600091908b16906370a0823190602401602060405180830381865afa158015612aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac49190613c4a565b9050612ad0838c613e1d565b9a50612adc8282613e1d565b612ae69089613d06565b97508a600003612af857505050612b06565b836001019350505050612747565b505050505b61179e565b600080612b1d8585612cf8565b6000612b2a878787610b00565b91505087811115612b71576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d65565b612b7b8682612e18565b9250612b888387876109f7565b9250612b979050858584612f63565b509550959350505050565b600080612baf8585612cf8565b6000612bbc878787610b00565b915050612bc98682612e18565b9250808314612c04576040517f0c5c1c2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87831115612c48576040517f71b5f0c10000000000000000000000000000000000000000000000000000000081526004810182905260248101899052604401610d65565b612c53858589612f63565b50909694955050505050565b600054610100900460ff16612cdc5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b612ce584613250565b612ced6132de565b61158d838383613363565b60ff546000906001600160a01b031615801590612d95575060ff546040517f6c059fb10000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690636c059fb190602401602060405180830381865afa158015612d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d959190613ce4565b905080158015612de1575060026001600160a01b03808516600090815260fd602090815260408083209387168352929052206001015460ff166003811115612ddf57612ddf61398b565b145b156109f2576040517f03410cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600091849183918316906370a0823190602401602060405180830381865afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea59190613c4a565b60fe54909150612ec4906001600160a01b038481169133911687613428565b60fe546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526000918416906370a0823190602401602060405180830381865afa158015612f29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f4d9190613c4a565b9050612f598282613e1d565b9695505050505050565b6000612f6e84610bff565b905081811015612faa576040517f6bb2792900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83612fbf6001600160a01b03821685856123fc565b5050505050565b600061301b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134799092919063ffffffff16565b905080516000148061303c57508080602001905181019061303c9190613ce4565b6109f25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d65565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60fc546040517fb62cad690000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b62cad6990602401600060405180830381600087803b15801561317957600080fd5b505af115801561318d573d6000803e3d6000fd5b505060fc546040517f41976e090000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260009450670de0b6b3a76400009350879216906341976e0990602401602060405180830381865afa158015613201573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132259190613c4a565b61322f9190613c0d565b6132399190613d1e565b905060fb54811061324957600191505b5092915050565b600054610100900460ff166132cd5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6132d5613490565b61057381613515565b600054610100900460ff1661335b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e613592565b600054610100900460ff166133e05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6133e983611f49565b6133f282611800565b6133fb816124f4565b505060fe80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b6040516001600160a01b038085166024830152831660448201526064810182905261158d9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612441565b6060613488848460008561360f565b949350505050565b600054610100900460ff1661350d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e613701565b600054610100900460ff1661062c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b600054610100900460ff16611ec55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b6060824710156136875760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d65565b600080866001600160a01b031685876040516136a3919061402a565b60006040518083038185875af1925050503d80600081146136e0576040519150601f19603f3d011682016040523d82523d6000602084013e6136e5565b606091505b50915091506136f687838387613787565b979650505050505050565b600054610100900460ff1661377e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d65565b610c9e336124c3565b606083156137f65782516000036137ef576001600160a01b0385163b6137ef5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d65565b5081613488565b613488838381511561380b5781518083602001fd5b8060405162461bcd60e51b8152600401610d659190614046565b6001600160a01b038116811461057357600080fd5b60006020828403121561384c57600080fd5b8135610c8581613825565b60008060006060848603121561386c57600080fd5b83359250602084013561387e81613825565b9150604084013561388e81613825565b809150509250925092565b600080600080600060a086880312156138b157600080fd5b853594506020860135935060408601356138ca81613825565b925060608601356138da81613825565b915060808601356138ea81613825565b809150509295509295909350565b60008060006060848603121561390d57600080fd5b833561391881613825565b9250602084013561392881613825565b929592945050506040919091013590565b60006020828403121561394b57600080fd5b5035919050565b6000806040838503121561396557600080fd5b823561397081613825565b9150602083013561398081613825565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106139f1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b82815260408101610c8560208301846139ba565b60008083601f840112613a1b57600080fd5b50813567ffffffffffffffff811115613a3357600080fd5b6020830191508360208260061b8501011115613a4e57600080fd5b9250929050565b600080600080600060608688031215613a6d57600080fd5b8535613a7881613825565b9450602086013567ffffffffffffffff80821115613a9557600080fd5b818801915088601f830112613aa957600080fd5b813581811115613ab857600080fd5b8960208260051b8501011115613acd57600080fd5b602083019650809550506040880135915080821115613aeb57600080fd5b50613af888828901613a09565b969995985093965092949392505050565b60008060008385036080811215613b1f57600080fd5b8435613b2a81613825565b93506020850135613b3a81613825565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b6c57600080fd5b506040840190509250925092565b600080600080600060a08688031215613b9257600080fd5b8535613b9d81613825565b94506020860135613bad81613825565b93506040860135613bbd81613825565b92506060860135613bcd81613825565b949793965091946080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c4557613c45613bde565b500290565b600060208284031215613c5c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215613ca457600080fd5b813560048110610c8557600080fd5b8481526020810184905260808101613cce60408301856139ba565b613cdb60608301846139ba565b95945050505050565b600060208284031215613cf657600080fd5b81518015158114610c8557600080fd5b60008219821115613d1957613d19613bde565b500190565b600082613d54577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613d74578181015183820152602001613d5c565b8381111561158d5750506000910152565b60008151808452613d9d816020860160208601613d59565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b03831681526040602082015260006134886040830184613d85565b60006001600160a01b03808616835280851660208401525060606040830152613cdb6060830184613d85565b600082821015613e2f57613e2f613bde565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613eaa57613eaa613e34565b604052919050565b600067ffffffffffffffff821115613ecc57613ecc613e34565b5060051b60200190565b600082601f830112613ee757600080fd5b81516020613efc613ef783613eb2565b613e63565b82815260059290921b84018101918181019086841115613f1b57600080fd5b8286015b84811015613f365780518352918301918301613f1f565b509695505050505050565b60008060408385031215613f5457600080fd5b825167ffffffffffffffff80821115613f6c57600080fd5b818501915085601f830112613f8057600080fd5b81516020613f90613ef783613eb2565b82815260059290921b84018101918181019089841115613faf57600080fd5b948201945b83861015613fd6578551613fc781613825565b82529482019490820190613fb4565b91880151919650909350505080821115613fef57600080fd5b50613ffc85828601613ed6565b9150509250929050565b6000806040838503121561401957600080fd5b505080516020909101519092909150565b6000825161403c818460208701613d59565b9190910192915050565b602081526000610c856020830184613d8556fe736574436f6e76657273696f6e436f6e66696728616464726573732c616464726573732c436f6e76657273696f6e436f6e66696729a2646970667358221220c90768b57d16a90270136f659c9003d1890ce1f6dcc427a5e56b6e83cfbf87c164736f6c634300080d0033", "devdoc": { "author": "Venus", "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", @@ -1548,6 +1548,7 @@ "initialize(address,address,address,address,uint256)": { "params": { "accessControlManager_": "Access control manager contract address", + "baseAsset_": "Address of the base asset", "destinationAddress_": "Address at all incoming tokens will transferred to", "minAmountToConvert_": "Minimum amount to convert", "priceOracle_": "Resilient oracle address" @@ -1854,7 +1855,7 @@ "notice": "To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut. This function does not account for potential token transfer fees(in case of deflationary tokens)" }, "getAmountOut(uint256,address,address)": { - "notice": "To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)" + "notice": "To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn. This function does not account for potential token transfer fees(in case of deflationary tokens)The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut" }, "getUpdatedAmountIn(uint256,address,address)": { "notice": "To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut" @@ -2020,7 +2021,7 @@ "label": "conversionConfigurations", "offset": 0, "slot": "253", - "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5463_storage))" + "type": "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5493_storage))" }, { "astId": 3371, @@ -2055,7 +2056,7 @@ "type": "t_array(t_uint256)45_storage" }, { - "astId": 6813, + "astId": 6843, "contract": "contracts/TokenConverter/SingleTokenConverter.sol:SingleTokenConverter", "label": "baseAsset", "offset": 0, @@ -2107,31 +2108,31 @@ "label": "contract ResilientOracle", "numberOfBytes": "20" }, - "t_enum(ConversionAccessibility)5455": { + "t_enum(ConversionAccessibility)5485": { "encoding": "inplace", "label": "enum IAbstractTokenConverter.ConversionAccessibility", "numberOfBytes": "1" }, - "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5463_storage))": { + "t_mapping(t_address,t_mapping(t_address,t_struct(ConversionConfig)5493_storage))": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => mapping(address => struct IAbstractTokenConverter.ConversionConfig))", "numberOfBytes": "32", - "value": "t_mapping(t_address,t_struct(ConversionConfig)5463_storage)" + "value": "t_mapping(t_address,t_struct(ConversionConfig)5493_storage)" }, - "t_mapping(t_address,t_struct(ConversionConfig)5463_storage)": { + "t_mapping(t_address,t_struct(ConversionConfig)5493_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct IAbstractTokenConverter.ConversionConfig)", "numberOfBytes": "32", - "value": "t_struct(ConversionConfig)5463_storage" + "value": "t_struct(ConversionConfig)5493_storage" }, - "t_struct(ConversionConfig)5463_storage": { + "t_struct(ConversionConfig)5493_storage": { "encoding": "inplace", "label": "struct IAbstractTokenConverter.ConversionConfig", "members": [ { - "astId": 5458, + "astId": 5488, "contract": "contracts/TokenConverter/SingleTokenConverter.sol:SingleTokenConverter", "label": "incentive", "offset": 0, @@ -2139,12 +2140,12 @@ "type": "t_uint256" }, { - "astId": 5462, + "astId": 5492, "contract": "contracts/TokenConverter/SingleTokenConverter.sol:SingleTokenConverter", "label": "conversionAccess", "offset": 0, "slot": "1", - "type": "t_enum(ConversionAccessibility)5455" + "type": "t_enum(ConversionAccessibility)5485" } ], "numberOfBytes": "64" diff --git a/deployments/bscmainnet/solcInputs/91b55240df7761b1edcdbbc6fc102117.json b/deployments/bscmainnet/solcInputs/91b55240df7761b1edcdbbc6fc102117.json new file mode 100644 index 00000000..e5ccd92a --- /dev/null +++ b/deployments/bscmainnet/solcInputs/91b55240df7761b1edcdbbc6fc102117.json @@ -0,0 +1,123 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides 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} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling 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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\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.9.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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlledV8\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\n /// @notice Access control manager contract\n IAccessControlManagerV8 private _accessControlManager;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when access control manager contract address is changed\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n /// @notice Thrown when the action is prohibited by AccessControlManager\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Sets the address of AccessControlManager\n * @dev Admin function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n * @custom:event Emits NewAccessControlManager event\n * @custom:access Only Governance\n */\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Returns the address of the access control manager contract\n */\n function accessControlManager() external view returns (IAccessControlManagerV8) {\n return _accessControlManager;\n }\n\n /**\n * @dev Internal function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n */\n function _setAccessControlManager(address accessControlManager_) internal {\n require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n address oldAccessControlManager = address(_accessControlManager);\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title IAccessControlManagerV8\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\n */\ninterface IAccessControlManagerV8 is IAccessControl {\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) external;\n\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface OracleInterface {\n function getPrice(address asset) external view returns (uint256);\n}\n\ninterface ResilientOracleInterface is OracleInterface {\n function updatePrice(address vToken) external;\n\n function updateAssetPrice(address asset) external;\n\n function getUnderlyingPrice(address vToken) external view returns (uint256);\n}\n\ninterface TwapInterface is OracleInterface {\n function updateTwap(address asset) external returns (uint256);\n}\n\ninterface BoundValidatorInterface {\n function validatePriceWithAnchorPrice(\n address asset,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface VBep20Interface is IERC20Metadata {\n /**\n * @notice Underlying asset for this VToken\n */\n function underlying() external view returns (address);\n}\n" + }, + "@venusprotocol/oracle/contracts/ResilientOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"./interfaces/VBep20Interface.sol\";\nimport \"./interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ResilientOracle\n * @author Venus\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\n * \n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\n * for attacking the protocol.\n * \n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\n * \n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \n * \n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\n * market. The upper bound ratio represents the deviation between reported price (the price that’s being\n * validated) and the anchor price (the price we are validating against) above which the reported price will\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\n * should be true:\n\n```\nanchorRatio = anchorPrice/reporterPrice\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\n```\n\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \n * \n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\n * oracle to be stagnant and treat it like it's disabled.\n */\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\n /**\n * @dev Oracle roles:\n * **main**: The most trustworthy price source\n * **pivot**: Price oracle used as a loose sanity checker\n * **fallback**: The backup source when main oracle price is invalidated\n */\n enum OracleRole {\n MAIN,\n PIVOT,\n FALLBACK\n }\n\n struct TokenConfig {\n /// @notice asset address\n address asset;\n /// @notice `oracles` stores the oracles based on their role in the following order:\n /// [main, pivot, fallback],\n /// It can be indexed with the corresponding enum OracleRole value\n address[3] oracles;\n /// @notice `enableFlagsForOracles` stores the enabled state\n /// for each oracle in the same order as `oracles`\n bool[3] enableFlagsForOracles;\n }\n\n uint256 public constant INVALID_PRICE = 0;\n\n /// @notice Native market address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable nativeMarket;\n\n /// @notice VAI address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vai;\n\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\n /// and can serve as any underlying asset of a market that supports native tokens\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Bound validator contract address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n BoundValidatorInterface public immutable boundValidator;\n\n mapping(address => TokenConfig) private tokenConfigs;\n\n event TokenConfigAdded(\n address indexed asset,\n address indexed mainOracle,\n address indexed pivotOracle,\n address fallbackOracle\n );\n\n /// Event emitted when an oracle is set\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\n\n /// Event emitted when an oracle is enabled or disabled\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\n\n /**\n * @notice Checks whether an address is null or not\n */\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /**\n * @notice Checks whether token config exists by checking whether asset is null address\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\n * @param asset asset address\n */\n modifier checkTokenConfigExistence(address asset) {\n if (tokenConfigs[asset].asset == address(0)) revert(\"token config must exist\");\n _;\n }\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\n /// (e.g vETH on ethereum would not be supported, only vWETH)\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\n /// Set to address(0) of VAI is not existent.\n /// @param _boundValidator Address of the bound validator contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address nativeMarketAddress,\n address vaiAddress,\n BoundValidatorInterface _boundValidator\n ) notNullAddress(address(_boundValidator)) {\n nativeMarket = nativeMarketAddress;\n vai = vaiAddress;\n boundValidator = _boundValidator;\n\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract admin and sets the BoundValidator contract address\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n }\n\n /**\n * @notice Pauses oracle\n * @custom:access Only Governance\n */\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n _pause();\n }\n\n /**\n * @notice Unpauses oracle\n * @custom:access Only Governance\n */\n function unpause() external {\n _checkAccessAllowed(\"unpause()\");\n _unpause();\n }\n\n /**\n * @notice Batch sets token configs\n * @param tokenConfigs_ Token config array\n * @custom:access Only Governance\n * @custom:error Throws a length error if the length of the token configs array is 0\n */\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\n if (tokenConfigs_.length == 0) revert(\"length can't be 0\");\n uint256 numTokenConfigs = tokenConfigs_.length;\n for (uint256 i; i < numTokenConfigs; ) {\n setTokenConfig(tokenConfigs_[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Sets oracle for a given asset and role.\n * @dev Supplied asset **must** exist and main oracle may not be null\n * @param asset Asset address\n * @param oracle Oracle address\n * @param role Oracle role\n * @custom:access Only Governance\n * @custom:error Null address error if main-role oracle address is null\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\n */\n function setOracle(\n address asset,\n address oracle,\n OracleRole role\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"setOracle(address,address,uint8)\");\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\"can't set zero address to main oracle\");\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\n emit OracleSet(asset, oracle, uint256(role));\n }\n\n /**\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\n * @param asset Asset address\n * @param role Oracle role\n * @param enable Enabled boolean of the oracle\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n */\n function enableOracle(\n address asset,\n OracleRole role,\n bool enable\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"enableOracle(address,uint8,bool)\");\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\n emit OracleEnabled(asset, uint256(role), enable);\n }\n\n /**\n * @notice Updates the TWAP pivot oracle price.\n * @dev This function should always be called before calling getUnderlyingPrice\n * @param vToken vToken address\n */\n function updatePrice(address vToken) external override {\n address asset = _getUnderlyingAsset(vToken);\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @notice Updates the pivot oracle price. Currently using TWAP\n * @dev This function should always be called before calling getPrice\n * @param asset asset address\n */\n function updateAssetPrice(address asset) external {\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @dev Gets token config by asset address\n * @param asset asset address\n * @return tokenConfig Config for the asset\n */\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\n return tokenConfigs[asset];\n }\n\n /**\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\n * - Check if the oracle is paused globally\n * - Validate price from main oracle against pivot oracle\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\n * - Validate price from main oracle against fallback oracle if the second validation failed\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\n * main oracle price is returned.\n * @param vToken vToken address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n\n address asset = _getUnderlyingAsset(vToken);\n return _getPrice(asset);\n }\n\n /**\n * @notice Gets price of the asset\n * @param asset asset address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getPrice(address asset) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n return _getPrice(asset);\n }\n\n /**\n * @notice Sets/resets single token configs.\n * @dev main oracle **must not** be a null address\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress is thrown if asset address is null\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(\n tokenConfig.asset,\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\n );\n }\n\n /**\n * @notice Gets oracle and enabled status by asset address\n * @param asset asset address\n * @param role Oracle role\n * @return oracle Oracle address based on role\n * @return enabled Enabled flag of the oracle based on token config\n */\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\n oracle = tokenConfigs[asset].oracles[uint256(role)];\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\n }\n\n function _getPrice(address asset) internal view returns (uint256) {\n uint256 pivotPrice = INVALID_PRICE;\n\n // Get pivot oracle price, Invalid price if not available or error\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracleEnabled && pivotOracle != address(0)) {\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\n pivotPrice = pricePivot;\n } catch {}\n }\n\n // Compare main price and pivot price, return main price and if validation was successful\n // note: In case pivot oracle is not available but main price is available and\n // validation is successful, the main oracle price is returned.\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\n asset,\n pivotPrice,\n pivotOracleEnabled && pivotOracle != address(0)\n );\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\n\n // Compare fallback and pivot if main oracle comparision fails with pivot\n // Return fallback price when fallback price is validated successfully with pivot oracle\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\n\n // Lastly compare main price and fallback price\n if (\n mainPrice != INVALID_PRICE &&\n fallbackPrice != INVALID_PRICE &&\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\n ) {\n return mainPrice;\n }\n\n revert(\"invalid resilient oracle price\");\n }\n\n /**\n * @notice Gets a price for the provided asset\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\n * able to fetch a correct price\n * @param asset asset address\n * @param pivotPrice Pivot oracle price\n * @param pivotEnabled If pivot oracle is not empty and enabled\n * @return price USD price in scaled decimals\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\n * @return pivotValidated Boolean representing if the validation of main oracle price\n * and pivot oracle price were successful\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\n * address is null\n */\n function _getMainOraclePrice(\n address asset,\n uint256 pivotPrice,\n bool pivotEnabled\n ) internal view returns (uint256, bool) {\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\n if (mainOracleEnabled && mainOracle != address(0)) {\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\n if (!pivotEnabled) {\n return (mainOraclePrice, true);\n }\n if (pivotPrice == INVALID_PRICE) {\n return (mainOraclePrice, false);\n }\n return (\n mainOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\n * @param asset asset address\n * @return price USD price in 18 decimals\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\n * and pivot oracle price were successfull\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\n * address is null\n */\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\n if (fallbackEnabled && fallbackOracle != address(0)) {\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\n if (pivotPrice == INVALID_PRICE) {\n return (fallbackOraclePrice, false);\n }\n return (\n fallbackOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function returns the underlying asset of a vToken\n * @param vToken vToken address\n * @return asset underlying asset address\n */\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\n if (vToken == nativeMarket) {\n asset = NATIVE_TOKEN_ADDR;\n } else if (vToken == vai) {\n asset = vai;\n } else {\n asset = VBep20Interface(vToken).underlying();\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\nuint256 constant EXP_SCALE = 1e18;\n\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\nuint256 constant MANTISSA_ONE = EXP_SCALE;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\n" + }, + "@venusprotocol/solidity-utilities/contracts/validators.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\nerror ZeroAddressNotAllowed();\n\n/// @notice Thrown if the supplied value is 0 where it is not allowed\nerror ZeroValueNotAllowed();\n\n/// @notice Checks if the provided address is nonzero, reverts otherwise\n/// @param address_ Address to check\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\nfunction ensureNonzeroAddress(address address_) pure {\n if (address_ == address(0)) {\n revert ZeroAddressNotAllowed();\n }\n}\n\n/// @notice Checks if the provided value is nonzero, reverts otherwise\n/// @param value_ Value to check\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\nfunction ensureNonzeroValue(uint256 value_) pure {\n if (value_ == 0) {\n revert ZeroValueNotAllowed();\n }\n}\n" + }, + "contracts/Interfaces/IComptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IComptroller {\n function isComptroller() external view returns (bool);\n\n function markets(address) external view returns (bool);\n\n function getAllMarkets() external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IConverterNetwork.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAbstractTokenConverter } from \"../TokenConverter/IAbstractTokenConverter.sol\";\n\n/**\n * @title IConverterNetwork\n * @author Venus\n * @notice Interface implemented by `ConverterNetwork`.\n */\ninterface IConverterNetwork {\n /// @notice Adds new converter to the array\n /// @param _tokenConverter Address of the token converter\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Removes converter from the array\n /// @param _tokenConverter Address of the token converter\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice This function returns the array containing all the converters addresses\n /// @return Array containing all the converters addresses\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\n\n /// @notice This function checks for given address is converter or not\n /// @param _tokenConverter Address of the token converter\n /// @return boolean true if given address is converter otherwise false\n function isTokenConverter(address _tokenConverter) external view returns (bool);\n}\n" + }, + "contracts/Interfaces/IPoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IPoolRegistry {\n /// @notice Get VToken in the Pool for an Asset\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\n\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IRiskFund.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IRiskFund\n * @author Venus\n * @notice Interface implemented by `RiskFund`.\n */\ninterface IRiskFund {\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updatePoolState(\n address comptroller,\n address asset,\n uint256 amount\n ) external;\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n\n/**\n * @title IRiskFundGetters\n * @author Venus\n * @notice Interface implemented by `RiskFund` for getter methods.\n */\ninterface IRiskFundGetters {\n function convertibleBaseAsset() external view returns (address);\n}\n" + }, + "contracts/Interfaces/IVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IVToken {\n function underlying() external view returns (address);\n}\n" + }, + "contracts/Test/Mocks/MockConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\n\nimport { AbstractTokenConverter } from \"../../TokenConverter/AbstractTokenConverter.sol\";\nimport { IRiskFundGetters } from \"../../Interfaces/IRiskFund.sol\";\n\ncontract MockConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) public assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) public poolsAssetsReserves;\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n function mockPrivateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 balanceDiff\n ) external {\n _privateConversion(comptroller, tokenAddressOut, balanceDiff);\n }\n\n function AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) public initializer {\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n assetsReserves[tokenAddressIn] += convertedTokenInBalance;\n poolsAssetsReserves[comptroller][tokenAddressIn] += convertedTokenInBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @notice Get base asset address\n function _getDestinationBaseAsset() internal view override returns (address) {\n return IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/Test/Mocks/MockRiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { RiskFundConverter } from \"../../TokenConverter/RiskFundConverter.sol\";\n\ncontract MockRiskFundConverter is RiskFundConverter {\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) RiskFundConverter(corePoolComptroller_, vBNB_, nativeWrapped_) {}\n\n function postConversionHookMock(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) external {\n super._postConversionHook(tokenInAddress, tokenOutAddress, amountIn, amountOut);\n }\n\n function preTransferHookMock(address tokenOutAddress, uint256 amountOut) external {\n super._preTransferHook(tokenOutAddress, amountOut);\n }\n\n function setAssetsReserves(address asset, uint256 amount) external {\n assetsReserves[asset] = amount;\n }\n\n function setPoolsAssetsReserves(\n address comptroller,\n address asset,\n uint256 amount\n ) external {\n poolsAssetsReserves[comptroller][asset] = amount;\n }\n\n function getPoolsAssetsReserves(address comptroller, address asset) external view returns (uint256) {\n return poolsAssetsReserves[comptroller][asset];\n }\n\n function getAssetsReserves(address asset) external view returns (uint256) {\n return assetsReserves[asset];\n }\n}\n" + }, + "contracts/TokenConverter/AbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { MANTISSA_ONE, EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\nimport { IAbstractTokenConverter } from \"./IAbstractTokenConverter.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @title AbstractTokenConverter\n/// @author Venus\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\n/*\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\n *\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\n * a. convertExactTokensSupportingFeeOnTransferTokens\n * b. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\n * similar to Case I.\n *\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * a. convertExactTokens\n * b. convertForExactTokens\n * c. convertExactTokensSupportingFeeOnTransferTokens\n * d. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * similar to Case III.\n *\n * ------------------------------------------------------------------------------------------------------------------------------------\n * Example 1:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInAmount - 100\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\n * function for tokenIn as deflationary token.\n *\n * Example 2:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\n * tokenOutAmount - 70\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\n * ------------------------------------------------------------------------------------------------------------------------------------\n *\n * This contract also supports private conversion between the converters:\n * Private conversions:\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\n *\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\n *\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\n * tokenAddressOut: As base asset of that converter.\n *\n * ConverterNetwork:\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\n * and tokenAddressOut provided.\n *\n * findTokenConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\n *\n * findTokenConvertersForConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\n */\n\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Maximum incentive could be\n uint256 public constant MAX_INCENTIVE = 0.5e18;\n\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\n uint256 public minAmountToConvert;\n\n /// @notice Venus price oracle contract\n ResilientOracle public priceOracle;\n\n /// @notice conversion configurations for the existing pairs\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\n\n /// @notice Address that all incoming tokens are transferred to\n address public destinationAddress;\n\n /// @notice Boolean for if conversion is paused\n bool public conversionPaused;\n\n /// @notice Address of the converterNetwork contract\n IConverterNetwork public converterNetwork;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n uint256[45] private __gap;\n\n /// @notice Emitted when config is updated for tokens pair\n event ConversionConfigUpdated(\n address indexed tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 oldIncentive,\n uint256 newIncentive,\n ConversionAccessibility oldAccess,\n ConversionAccessibility newAccess\n );\n /// @notice Emitted when price oracle address is updated\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\n\n /// @notice Emitted when destination address is updated\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\n\n /// @notice Emitted when converterNetwork address is updated\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\n\n /// @notice Emitted when exact amount of tokens are converted for tokens\n event ConvertedExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens\n event ConvertedForExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when conversion is paused\n event ConversionPaused(address indexed sender);\n\n /// @notice Emitted when conversion is unpaused\n event ConversionResumed(address indexed sender);\n\n /// @notice Event emitted when tokens are swept\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\n error AmountOutMismatched();\n\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\n error AmountInMismatched();\n\n /// @notice Thrown when given input amount is zero\n error InsufficientInputAmount();\n\n /// @notice Thrown when given output amount is zero\n error InsufficientOutputAmount();\n\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\n error ConversionConfigNotEnabled();\n\n /// @notice Thrown when conversion is enabled only for private conversions\n error ConversionEnabledOnlyForPrivateConversions();\n\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n error InvalidToAddress();\n\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\n\n /// @notice Thrown when amountOut is lower than amountOutMin\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\n\n /// @notice Thrown when amountIn is higher than amountInMax\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\n\n /// @notice Thrown when conversion is paused\n error ConversionTokensPaused();\n\n /// @notice Thrown when conversion is Active\n error ConversionTokensActive();\n\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\n error InvalidTokenConfigAddresses();\n\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\n error InsufficientPoolLiquidity();\n\n /// @notice When address of the ConverterNetwork is not set or Zero address\n error InvalidConverterNetwork();\n\n /// @notice Thrown when trying to set non zero incentive for private conversion\n error NonZeroIncentiveForPrivateConversion();\n\n /// @notice Thrown when using convertForExactTokens deflationary tokens\n error DeflationaryTokenNotSupported();\n\n /// @notice Thrown when minimum amount to convert is zero\n error InvalidMinimumAmountToConvert();\n\n /// @notice Thrown when there is a mismatch in the length of input arrays\n error InputLengthMisMatch();\n\n /**\n * @notice Modifier to ensure valid conversion parameters for a token conversion\n * and check if conversion is paused or not\n * @param to The recipient address for the converted tokens\n * @param tokenAddressIn The input token address for the conversion\n * @param tokenAddressOut The output token address for the conversion\n */\n modifier validConversionParameters(\n address to,\n address tokenAddressIn,\n address tokenAddressOut\n ) {\n _checkConversionPaused();\n ensureNonzeroAddress(to);\n if (to == tokenAddressIn || to == tokenAddressOut) {\n revert InvalidToAddress();\n }\n _;\n }\n\n /// @notice Pause conversion of tokens\n /// @custom:event Emits ConversionPaused on success\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\n /// @custom:access Restricted by ACM\n function pauseConversion() external {\n _checkAccessAllowed(\"pauseConversion()\");\n _checkConversionPaused();\n conversionPaused = true;\n emit ConversionPaused(msg.sender);\n }\n\n /// @notice Resume conversion of tokens.\n /// @custom:event Emits ConversionResumed on success\n /// @custom:error ConversionTokensActive thrown when conversion is already active\n /// @custom:access Restricted by ACM\n function resumeConversion() external {\n _checkAccessAllowed(\"resumeConversion()\");\n if (!conversionPaused) {\n revert ConversionTokensActive();\n }\n\n conversionPaused = false;\n emit ConversionResumed(msg.sender);\n }\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:access Only Governance\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\n _setPriceOracle(priceOracle_);\n }\n\n /// @notice Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:access Only Governance\n function setDestination(address destinationAddress_) external onlyOwner {\n _setDestination(destinationAddress_);\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:access Only Governance\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\n _setConverterNetwork(converterNetwork_);\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:access Only Governance\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n _setMinAmountToConvert(minAmountToConvert_);\n }\n\n /// @notice Batch sets the conversion configurations\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressesOut Array of addresses of tokenOut\n /// @param conversionConfigs Array of conversionConfig config details to update\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\n function setConversionConfigs(\n address tokenAddressIn,\n address[] calldata tokenAddressesOut,\n ConversionConfig[] calldata conversionConfigs\n ) external {\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\n\n for (uint256 i; i < tokenOutArrayLength; ) {\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountIn != amountInMantissa) {\n revert AmountInMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\n /// otherwise the amount is adjusted\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountOut != amountOutMantissa) {\n revert AmountOutMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\n /// @param tokenAddress The address of the ERC-20 token to sweep\n /// @param to The address to which tokens will be transferred\n /// @param amount The amount to transfer\n /// @custom:event Emits SweepToken event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\n /// @custom:access Only Governance\n function sweepToken(\n address tokenAddress,\n address to,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(to);\n ensureNonzeroValue(amount);\n\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n preSweepToken(tokenAddress, amount);\n token.safeTransfer(to, amount);\n\n emit SweepToken(tokenAddress, to, amount);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @notice The amountInMantissa might be adjusted if amountOutMantissa is greater than the balance of the contract for tokenAddressOut\n /// @dev This function retrieves values without altering token prices\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n amountConvertedMantissa = amountInMantissa;\n uint256 tokenInToOutConversion;\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountConvertedMantissa = _divRoundingUp(maxTokenOutReserve * EXP_SCALE, tokenInToOutConversion);\n amountOutMantissa = maxTokenOutReserve;\n }\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @dev This function retrieves values without altering token prices\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountOutMantissa = maxTokenOutReserve;\n }\n\n amountConvertedMantissa = amountOutMantissa;\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountInMantissa;\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountOutMantissa;\n }\n\n /// @notice This method updated the states of this contract after getting funds from PSR\n /// after settling the amount(if any) through privateConversion between converters\n /// @dev This function is called by protocolShareReserve\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\n if (balanceDiff > 0) {\n _privateConversion(comptroller, asset, balanceDiff);\n }\n }\n\n /// @notice Set the configuration for new or existing conversion pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n /// @custom:event Emits ConversionConfigUpdated event on success\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\n /// @custom:access Controlled by AccessControlManager\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) public {\n _checkAccessAllowed(\"setConversionConfig(address,address,ConversionConfig)\");\n ensureNonzeroAddress(tokenAddressIn);\n ensureNonzeroAddress(tokenAddressOut);\n\n if (conversionConfig.incentive > MAX_INCENTIVE) {\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\n }\n\n if (\n (tokenAddressIn == tokenAddressOut) ||\n (tokenAddressIn != _getDestinationBaseAsset()) ||\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\n ) {\n revert InvalidTokenConfigAddresses();\n }\n\n if (\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\n conversionConfig.incentive != 0\n ) {\n revert NonZeroIncentiveForPrivateConversion();\n }\n\n if (\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\n (address(converterNetwork) == address(0))\n ) {\n revert InvalidConverterNetwork();\n }\n\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n emit ConversionConfigUpdated(\n tokenAddressIn,\n tokenAddressOut,\n configuration.incentive,\n conversionConfig.incentive,\n configuration.conversionAccess,\n conversionConfig.conversionAccess\n );\n\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\n } else {\n configuration.incentive = conversionConfig.incentive;\n configuration.conversionAccess = conversionConfig.conversionAccess;\n }\n }\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\n\n /// @dev Operations to perform before sweeping tokens\n /// @param token Address of the token\n /// @param amount Amount transferred to address(to)\n function preSweepToken(address token, uint256 amount) internal virtual {}\n\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function _convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n if (amountOutMantissa < amountOutMinMantissa) {\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n }\n\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\n /// it is called by convertForExactTokens function\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n if (actualAmountIn != amountInMantissa) {\n revert DeflationaryTokenNotSupported();\n }\n\n if (actualAmountIn > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n actualAmountOut = amountOutMantissa;\n }\n\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\n /// @notice Advising users to input a smaller amountOutMantissa to avoid potential transaction revert\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n if (amountInMantissa > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\n }\n\n /// @dev return actualAmountOut from reserves for tokenAddressOut\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\n function _doTransferOut(\n address tokenAddressOut,\n address to,\n uint256 amountConvertedMantissa\n ) internal {\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountConvertedMantissa) {\n revert InsufficientPoolLiquidity();\n }\n\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\n\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\n tokenOut.safeTransfer(to, amountConvertedMantissa);\n }\n\n /// @notice Transfer tokenAddressIn from user to destination\n /// @param tokenAddressIn Address of the token to convert\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @return actualAmountIn Actual amount transferred to destination\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\n }\n\n /// @dev Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:event Emits PriceOracleUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\n ensureNonzeroAddress(address(priceOracle_));\n emit PriceOracleUpdated(priceOracle, priceOracle_);\n priceOracle = priceOracle_;\n }\n\n /// @dev Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:event Emits DestinationAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\n function _setDestination(address destinationAddress_) internal {\n ensureNonzeroAddress(destinationAddress_);\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\n destinationAddress = destinationAddress_;\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\n ensureNonzeroAddress(address(converterNetwork_));\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\n converterNetwork = converterNetwork_;\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:event MinAmountToConvertUpdated is emitted in success\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\n ensureNonzeroValue(minAmountToConvert_);\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\n minAmountToConvert = minAmountToConvert_;\n }\n\n /// @dev Hook to perform after converting tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param amountIn Amount of tokenIn converted\n /// @param amountOut Amount of tokenOut converted\n function _postConversionHook(\n address tokenAddressIn,\n address tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n ) internal virtual {}\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init_unchained(\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n _setPriceOracle(priceOracle_);\n _setDestination(destinationAddress_);\n _setMinAmountToConvert(minAmountToConvert_);\n conversionPaused = false;\n }\n\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return Amount of asset, for _privateConversion\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\n\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\n /// destination contract as destination's base asset\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\n function _privateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 amountToConvert\n ) internal {\n address tokenAddressIn = _getDestinationBaseAsset();\n address _destinationAddress = destinationAddress;\n uint256 convertedTokenInBalance;\n if (address(converterNetwork) != address(0)) {\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\n uint256 convertersLength = converterAddresses.length;\n for (uint256 i; i < convertersLength; ) {\n if (converterBalances[i] == 0) break;\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\n converterBalances[i],\n tokenAddressOut,\n tokenAddressIn\n );\n if (amountIn > amountToConvert) {\n amountIn = amountToConvert;\n }\n\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\n break;\n }\n\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\n amountIn,\n 0,\n tokenAddressOut,\n tokenAddressIn,\n _destinationAddress\n );\n\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n amountToConvert -= amountIn;\n convertedTokenInBalance += (balanceAfter - balanceBefore);\n\n if (amountToConvert == 0) break;\n unchecked {\n ++i;\n }\n }\n }\n\n _postPrivateConversionHook(\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance,\n tokenAddressOut,\n amountToConvert\n );\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal virtual {}\n\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\n\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\n /// @param amountIn The amount to convert\n /// @param tokenAddress Address of the token\n /// @return isValid true if amount to convert is greater than minimum amount to convert\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\n priceOracle.updateAssetPrice(tokenAddress);\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\n\n if (amountInInUsd >= minAmountToConvert) {\n isValid = true;\n }\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\n if (amountInMantissa == 0) {\n revert InsufficientInputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\n /// multiplied by conversionWithIncentive which will be >= 1\n amountOutMantissa = (amountInMantissa * tokenInToOutConversion) / (EXP_SCALE);\n }\n\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @dev For user conversions, the function returns an amountInMantissa that is rounded up, ensuring that the equivalent amountInMantissa\n /// is obtained from users for corresponding amountOutMantissa, preventing any losses to the protocol. However, no rounding up is required for private conversions\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\n if (amountOutMantissa == 0) {\n revert InsufficientOutputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n\n bool isPrivateConversion = address(converterNetwork) != address(0) &&\n converterNetwork.isTokenConverter(msg.sender);\n if (isPrivateConversion) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\n if (isPrivateConversion) {\n amountInMantissa =\n (amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE) /\n (tokenInUnderlyingPrice * conversionWithIncentive);\n } else {\n amountInMantissa = _divRoundingUp(\n amountOutMantissa * tokenOutUnderlyingPrice * EXP_SCALE,\n tokenInUnderlyingPrice * conversionWithIncentive\n );\n }\n\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n }\n\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\n if (\n (!(isConverter) &&\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n }\n\n /// @dev To check, is conversion paused\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\n function _checkConversionPaused() internal view {\n if (conversionPaused) {\n revert ConversionTokensPaused();\n }\n }\n\n /// @dev Get base asset address of the destination contract\n /// @return Address of the base asset\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\n\n /// @dev Performs division where the result is rounded up\n /// @param numerator The numerator of the division operation\n /// @param denominator The denominator of the division operation. Must be non-zero\n /// @return The result of the division, rounded up\n function _divRoundingUp(uint256 numerator, uint256 denominator) internal pure returns (uint256) {\n return (numerator + denominator - 1) / denominator;\n }\n}\n" + }, + "contracts/TokenConverter/IAbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @notice Interface for AbstractTokenConverter\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ninterface IAbstractTokenConverter {\n /// @notice This enum define the all possible ways of conversion can happen\n enum ConversionAccessibility {\n NONE, // Conversion is disable for the pair\n ALL, // Conversion is enable for private conversion and users\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\n ONLY_FOR_USERS // Conversion is enable only for users\n }\n\n /// @notice This struct represents the configuration for a token conversion.\n struct ConversionConfig {\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\n uint256 incentive;\n /// enable or disable conversion for users or converters or both or none\n ConversionAccessibility conversionAccess;\n }\n\n /// @notice Pause conversion of tokens\n function pauseConversion() external;\n\n /// @notice Resume conversion of tokens.\n function resumeConversion() external;\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n function setPriceOracle(ResilientOracle priceOracle_) external;\n\n /// @notice Set the configuration for new or existing convert pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) external;\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Get the configuration for the pair of the tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\n /// @return conversionAccess Accessibility for the pair of tokens\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\n external\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\n\n /// @notice Get the address of the converterNetwork\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) external view returns (uint256 tokenBalance);\n}\n" + }, + "contracts/TokenConverter/RiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\nimport { IPoolRegistry } from \"../Interfaces/IPoolRegistry.sol\";\nimport { IComptroller } from \"../Interfaces/IComptroller.sol\";\nimport { IRiskFund, IRiskFundGetters } from \"../Interfaces/IRiskFund.sol\";\nimport { IVToken } from \"../Interfaces/IVToken.sol\";\n\n/// @title RiskFundConverter\n/// @author Venus\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the core pool comptroller\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n ///@notice Address of the vBNB\n ///@dev This address is used to include the BNB market while in getPools method\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable VBNB;\n\n ///@notice Address of the native wrapped currency\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_WRAPPED;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) internal assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\n\n /// @notice Address of pool registry contract\n address public poolRegistry;\n\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\n\n // Error thrown when comptrollers array length is not equal to assets array length\n error InvalidArguments();\n\n /// @notice thrown when amount entered is greater than balance\n error InsufficientBalance();\n\n /// @notice thrown when asset does not exist in the pool\n error MarketNotExistInPool(address comptroller, address asset);\n\n /// @notice thrown to prevent reentrancy\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\n /// cannot be called recursively within the same transaction.\n error ReentrancyGuardError();\n\n /// @param corePoolComptroller_ Address of the Comptroller pool\n /// @param vBNB_ Address of the vBNB\n /// @param nativeWrapped_ Address of the wrapped native currency\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) {\n ensureNonzeroAddress(corePoolComptroller_);\n ensureNonzeroAddress(vBNB_);\n ensureNonzeroAddress(nativeWrapped_);\n\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\n VBNB = vBNB_;\n NATIVE_WRAPPED = nativeWrapped_;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param poolRegistry_ Address of the pool registry\n /// @param minAmountToConvert_ minimum amount to convert\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address poolRegistry_,\n uint256 minAmountToConvert_,\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) public initializer {\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n ensureNonzeroAddress(poolRegistry_);\n poolRegistry = poolRegistry_;\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Pool registry setter\n /// @param poolRegistry_ Address of the pool registry\n /// @custom:event PoolRegistryUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:access Only Governance\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\n poolRegistry = poolRegistry_;\n }\n\n /// @notice Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:access Restricted by ACM\n function setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) external {\n _checkAccessAllowed(\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\");\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return reserves Asset's reserve in risk fund\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n reserves = poolsAssetsReserves[comptroller][asset];\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Reserves of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n tokenBalance = assetsReserves[tokenAddress];\n }\n\n /// @notice Get the array of all pools addresses\n /// @param tokenAddress Address of the token\n /// @return poolsWithCore Array of the pools addresses in which token is available\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\n\n if (isAssetListedInCore(tokenAddress)) {\n uint256 poolsLength = poolsWithCore.length;\n address[] memory extendedPools = new address[](poolsLength + 1);\n\n for (uint256 i; i < poolsLength; ) {\n extendedPools[i] = poolsWithCore[i];\n unchecked {\n ++i;\n }\n }\n\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\n poolsWithCore = extendedPools;\n }\n }\n\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\n assetsReserves[tokenOutAddress] -= amountOut;\n }\n\n /// @notice Hook to perform after converting tokens\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\n /// @param tokenInAddress Address of the tokenIn\n /// @param tokenOutAddress Address of the tokenOut\n /// @param amountIn Amount of tokenIn transferred\n /// @param amountOut Amount of tokenOut transferred\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\n function _postConversionHook(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) internal override {\n address[] memory pools = getPools(tokenOutAddress);\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\n ensureNonzeroValue(assetReserve);\n\n uint256 poolsLength = pools.length;\n uint256 distributedOutShare;\n uint256 poolAmountInShare;\n uint256 distributedInShare;\n\n for (uint256 i; i < poolsLength; ) {\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\n if (currentPoolsAssetsReserves != 0) {\n if (i < (poolsLength - 1)) {\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\n distributedInShare += poolAmountInShare;\n } else {\n uint256 distributedDiff = amountOut - distributedOutShare;\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\n poolAmountInShare = amountIn - distributedInShare;\n }\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\n }\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Operations to perform before sweeping tokens\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\n if (amount > balance) revert InsufficientBalance();\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\n\n if (balanceDiff < amount) {\n uint256 amountDiff;\n unchecked {\n amountDiff = amount - balanceDiff;\n }\n\n address[] memory pools = getPools(tokenAddress);\n uint256 assetReserve = assetsReserves[tokenAddress];\n uint256 poolsLength = pools.length;\n uint256 distributedShare;\n\n for (uint256 i; i < poolsLength; ) {\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\n if (i < (poolsLength - 1)) {\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\n } else {\n uint256 distributedDiff = amountDiff - distributedShare;\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\n }\n }\n unchecked {\n ++i;\n }\n }\n assetsReserves[tokenAddress] -= amountDiff;\n }\n }\n\n /// @dev Update the poolAssetsReserves upon transferring the tokens\n /// @param pool Address of the pool\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @param assetReserve Asset's reserve for the pool\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\n /// @custom:event AssetsReservesUpdated emits on success\n function updatePoolAssetsReserve(\n address pool,\n address tokenAddress,\n uint256 amount,\n uint256 assetReserve\n ) internal returns (uint256 poolAmountShare) {\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\n }\n\n /// @dev Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\n function _setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) internal {\n uint256 comptrollersLength = comptrollers.length;\n\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < comptrollersLength; ) {\n address[] memory poolAssets = assets[i];\n bool[] memory assetsValues = values[i];\n uint256 poolAssetsLength = poolAssets.length;\n\n if (poolAssetsLength != assetsValues.length) {\n revert InvalidArguments();\n }\n\n for (uint256 j; j < poolAssetsLength; ) {\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\n unchecked {\n ++j;\n }\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\n /// and transferring funds to the protocol share reserve\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return balanceDifference Amount of asset, for _privateConversion\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n function _updateAssetsState(address comptroller, address asset)\n internal\n override\n returns (uint256 balanceDifference)\n {\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 currentBalance = token.balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\n token.safeTransfer(destinationAddress, balanceDifference);\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\n\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\n IRiskFund(destinationAddress).updatePoolState(\n comptroller,\n asset,\n newDestinationBalance - previousDestinationBalance\n );\n balanceDifference = 0;\n }\n }\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n emit AssetTransferredToDestination(\n destinationAddress,\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance\n );\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @dev This function checks for the given asset is listed in core pool or not\n /// @param tokenAddress Address of the asset\n /// @return isAssetListed true if the asset is listed\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\n\n uint256 coreMarketsLength = coreMarkets.length;\n for (uint256 i; i < coreMarketsLength; ) {\n isAssetListed = (VBNB == coreMarkets[i])\n ? (tokenAddress == NATIVE_WRAPPED)\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\n\n if (isAssetListed) {\n break;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev This function checks for the given asset is listed or not\n /// @param comptroller Address of the comptroller\n /// @param asset Address of the asset\n /// @return isListed true if the asset is listed\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\n if (comptroller == CORE_POOL_COMPTROLLER) {\n isListed = isAssetListedInCore(asset);\n } else {\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\n }\n }\n\n /// @dev Get base asset address of the RiskFund\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/TokenConverter/SingleTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\n\n/// @title SingleTokenConverter\n/// @author Venus\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract SingleTokenConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the base asset token\n address public baseAsset;\n\n /// @notice Emitted when base asset is updated\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param baseAsset_ Address of the base asset\n /// @param minAmountToConvert_ Minimum amount to convert\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address baseAsset_,\n uint256 minAmountToConvert_\n ) public initializer {\n _setBaseAsset(baseAsset_);\n\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @notice Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:access Only Governance\n function setBaseAsset(address baseAsset_) external onlyOwner {\n _setBaseAsset(baseAsset_);\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address.\n /// @return balanceLeft Amount of asset, for _privateConversion\n // solhint-disable-next-line\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 balance = token.balanceOf(address(this));\n balanceLeft = balance;\n\n if (asset == baseAsset) {\n balanceLeft = 0;\n token.safeTransfer(destinationAddress, balance);\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\n }\n }\n\n /// @dev Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n /// @custom:event BaseAssetUpdated is emitted on success\n function _setBaseAsset(address baseAsset_) internal {\n ensureNonzeroAddress(baseAsset_);\n emit BaseAssetUpdated(baseAsset, baseAsset_);\n baseAsset = baseAsset_;\n }\n\n /// @dev Get base asset address\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = baseAsset;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} From eed49a2bb43964ad431dd296dabbcf83aa348a6a Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 28 Feb 2024 13:55:10 +0000 Subject: [PATCH 36/53] feat: updating deployment files --- deployments/bscmainnet.json | 4 ++-- deployments/bscmainnet_addresses.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/deployments/bscmainnet.json b/deployments/bscmainnet.json index 184cf9d1..9a01460f 100644 --- a/deployments/bscmainnet.json +++ b/deployments/bscmainnet.json @@ -5127,7 +5127,7 @@ ] }, "RiskFundConverter_Implementation": { - "address": "0x2fB02b3D49D45967DA471C7685Ce524d833520Dc", + "address": "0xd420Bf9C31F6b4a98875B6e561b13aCB19210647", "abi": [ { "inputs": [ @@ -7632,7 +7632,7 @@ ] }, "SingleTokenConverterImp": { - "address": "0xe80f5A2adE24bEd740408B944197b3c24f2f2e91", + "address": "0x40ed28180Df01FdeB957224E4A5415704B9D5990", "abi": [ { "inputs": [], diff --git a/deployments/bscmainnet_addresses.json b/deployments/bscmainnet_addresses.json index adcf8f98..ea423864 100644 --- a/deployments/bscmainnet_addresses.json +++ b/deployments/bscmainnet_addresses.json @@ -12,11 +12,11 @@ "ProtocolShareReserve_Implementation": "0x86a2a5EB77984E923E7B5Af45819A8c8f870f061", "ProtocolShareReserve_Proxy": "0xCa01D5A9A248a830E9D93231e791B1afFed7c446", "RiskFundConverter": "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0", - "RiskFundConverter_Implementation": "0x2fB02b3D49D45967DA471C7685Ce524d833520Dc", + "RiskFundConverter_Implementation": "0xd420Bf9C31F6b4a98875B6e561b13aCB19210647", "RiskFundConverter_Proxy": "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0", "RiskFundV2": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", "SingleTokenConverterBeacon": "0x4c9D57b05B245c40235D720A5f3A592f3DfF11ca", - "SingleTokenConverterImp": "0xe80f5A2adE24bEd740408B944197b3c24f2f2e91", + "SingleTokenConverterImp": "0x40ed28180Df01FdeB957224E4A5415704B9D5990", "USDCPrimeConverter": "0xa758c9C215B6c4198F0a0e3FA46395Fa15Db691b", "USDTPrimeConverter": "0xD9f101AA67F3D72662609a2703387242452078C3", "XVSVaultConverter": "0xd5b9AE835F4C59272032B3B954417179573331E0", From 1dd86ce05baa40450c332578a16d56f8f3750f3a Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Thu, 29 Feb 2024 15:16:05 -0300 Subject: [PATCH 37/53] chore: remove unnecessary venus-protocol dependency --- hardhat.config.ts | 3 --- package.json | 1 - yarn.lock | 21 ++------------------- 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 64603b5d..3a9083d1 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -23,19 +23,16 @@ const DEPLOYER_PRIVATE_KEY = process.env.DEPLOYER_PRIVATE_KEY; // when the export deployment command executes independently for each network. const externalDeployments = { bsctestnet: [ - "node_modules/@venusprotocol/venus-protocol/deployments/bsctestnet", "node_modules/@venusprotocol/governance-contracts/deployments/bsctestnet", "node_modules/@venusprotocol/oracle/deployments/bsctestnet", "node_modules/@venusprotocol/isolated-pools/deployments/bsctestnet", ], sepolia: [ - "node_modules/@venusprotocol/venus-protocol/deployments/sepolia", "node_modules/@venusprotocol/governance-contracts/deployments/sepolia", "node_modules/@venusprotocol/oracle/deployments/sepolia", "node_modules/@venusprotocol/isolated-pools/deployments/sepolia", ], bscmainnet: [ - "node_modules/@venusprotocol/venus-protocol/deployments/bscmainnet", "node_modules/@venusprotocol/governance-contracts/deployments/bscmainnet", "node_modules/@venusprotocol/oracle/deployments/bscmainnet", "node_modules/@venusprotocol/isolated-pools/deployments/bscmainnet", diff --git a/package.json b/package.json index a5e5db89..8e0d6b52 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "@typescript-eslint/parser": "^5.44.0", "@venusprotocol/governance-contracts": "^1.4.0", "@venusprotocol/oracle": "^1.8.0", - "@venusprotocol/venus-protocol": "^7.0.0", "bignumber.js": "^9.1.1", "chai": "^4.3.7", "dotenv": "^16.0.3", diff --git a/yarn.lock b/yarn.lock index 7e040e47..2bbdc7f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2974,7 +2974,7 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/protocol-reserve@npm:^1.1.0, @venusprotocol/protocol-reserve@npm:^1.2.0": +"@venusprotocol/protocol-reserve@npm:^1.1.0": version: 1.4.0 resolution: "@venusprotocol/protocol-reserve@npm:1.4.0" dependencies: @@ -3023,7 +3023,6 @@ __metadata: "@venusprotocol/isolated-pools": ^2.3.0 "@venusprotocol/oracle": ^1.8.0 "@venusprotocol/solidity-utilities": ^1.3.0 - "@venusprotocol/venus-protocol": ^7.0.0 bignumber.js: ^9.1.1 chai: ^4.3.7 dotenv: ^16.0.3 @@ -3054,7 +3053,7 @@ __metadata: languageName: unknown linkType: soft -"@venusprotocol/solidity-utilities@npm:1.3.0, @venusprotocol/solidity-utilities@npm:^1.2.0, @venusprotocol/solidity-utilities@npm:^1.3.0": +"@venusprotocol/solidity-utilities@npm:1.3.0, @venusprotocol/solidity-utilities@npm:^1.3.0": version: 1.3.0 resolution: "@venusprotocol/solidity-utilities@npm:1.3.0" checksum: d1109365a5e01959c47b25fb129373db93792e60bf1bc0ed324b63c2a64f6e4a7878ebf016cfade94bc41a2c1245d3e861fdc6b8c5844ac210ed1d73e7307e72 @@ -3083,22 +3082,6 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/venus-protocol@npm:^7.0.0": - version: 7.0.0 - resolution: "@venusprotocol/venus-protocol@npm:7.0.0" - dependencies: - "@openzeppelin/contracts": 4.9.3 - "@openzeppelin/contracts-upgradeable": ^4.8.0 - "@venusprotocol/governance-contracts": ^1.4.0 - "@venusprotocol/protocol-reserve": ^1.2.0 - "@venusprotocol/solidity-utilities": ^1.2.0 - bignumber.js: ^9.1.2 - dotenv: ^16.0.1 - module-alias: ^2.2.2 - checksum: 02c6d28817582a8fd149773373c29d61adcdd5f8101661bec4ff3bcd4ecab76edb7a416105ea88de80de4e630c59695c493e13051c7b57c2c10b9a635b7cd5c6 - languageName: node - linkType: hard - "JSONStream@npm:^1.0.4, JSONStream@npm:^1.3.5": version: 1.3.5 resolution: "JSONStream@npm:1.3.5" From b0c59008d35aac533a1b8d319ad417999a75e01c Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Tue, 5 Mar 2024 06:06:16 +0000 Subject: [PATCH 38/53] chore(release): 1.5.0-dev.4 [skip ci] ## [1.5.0-dev.4](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.3...v1.5.0-dev.4) (2024-03-05) ### Features * update converter implementation deployment files ([9590f0a](https://github.com/VenusProtocol/protocol-reserve/commit/9590f0a51d61b9a33d59e7350667662950922fed)) * update converters deployment files for bscmainnet ([8dc80e9](https://github.com/VenusProtocol/protocol-reserve/commit/8dc80e99923419147b85021a19733820e16e5ddb)) * update converters deployment files for bsctestnet ([65da556](https://github.com/VenusProtocol/protocol-reserve/commit/65da55607d26bd43689e4fa5467f6fa7d7904ea1)) * updating deployment files ([eed49a2](https://github.com/VenusProtocol/protocol-reserve/commit/eed49a2bb43964ad431dd296dabbcf83aa348a6a)) * updating deployment files ([dced648](https://github.com/VenusProtocol/protocol-reserve/commit/dced648d3085d324b5f27012a1de4f3cfc9630c2)) * updating deployment files ([987a287](https://github.com/VenusProtocol/protocol-reserve/commit/987a2874e487076318e0f4f8d5e173ab9111e2a4)) ### Bug Fixes * _getAmountOut normalisation ([20d9df9](https://github.com/VenusProtocol/protocol-reserve/commit/20d9df919005adf5de618edd7377cebf271d58af)) * amountOutMantissa in _getAmountOut() ([6c74d7b](https://github.com/VenusProtocol/protocol-reserve/commit/6c74d7b4bd63c69bc931a238e2f46ed4a6e797ef)) * lint ([09885c0](https://github.com/VenusProtocol/protocol-reserve/commit/09885c04d73f4d858f23a68962cdcc72e899d260)) * round up for _getAmountIn ([498441f](https://github.com/VenusProtocol/protocol-reserve/commit/498441f21f92d38cb68bb76f3269cb38758e5ce1)) * round-up condition suggested by certik ([5486b99](https://github.com/VenusProtocol/protocol-reserve/commit/5486b9909b5d1a2257b8ac7287509e4cd697cd2b)) * spelling ([a3bd0b8](https://github.com/VenusProtocol/protocol-reserve/commit/a3bd0b8e5073410adbc426034cd6cf42a6043e5e)) --- CHANGELOG.md | 22 ++++++++++++++++++++++ package.json | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06d0a4ce..0e78e3a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +## [1.5.0-dev.4](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.3...v1.5.0-dev.4) (2024-03-05) + + +### Features + +* update converter implementation deployment files ([9590f0a](https://github.com/VenusProtocol/protocol-reserve/commit/9590f0a51d61b9a33d59e7350667662950922fed)) +* update converters deployment files for bscmainnet ([8dc80e9](https://github.com/VenusProtocol/protocol-reserve/commit/8dc80e99923419147b85021a19733820e16e5ddb)) +* update converters deployment files for bsctestnet ([65da556](https://github.com/VenusProtocol/protocol-reserve/commit/65da55607d26bd43689e4fa5467f6fa7d7904ea1)) +* updating deployment files ([eed49a2](https://github.com/VenusProtocol/protocol-reserve/commit/eed49a2bb43964ad431dd296dabbcf83aa348a6a)) +* updating deployment files ([dced648](https://github.com/VenusProtocol/protocol-reserve/commit/dced648d3085d324b5f27012a1de4f3cfc9630c2)) +* updating deployment files ([987a287](https://github.com/VenusProtocol/protocol-reserve/commit/987a2874e487076318e0f4f8d5e173ab9111e2a4)) + + +### Bug Fixes + +* _getAmountOut normalisation ([20d9df9](https://github.com/VenusProtocol/protocol-reserve/commit/20d9df919005adf5de618edd7377cebf271d58af)) +* amountOutMantissa in _getAmountOut() ([6c74d7b](https://github.com/VenusProtocol/protocol-reserve/commit/6c74d7b4bd63c69bc931a238e2f46ed4a6e797ef)) +* lint ([09885c0](https://github.com/VenusProtocol/protocol-reserve/commit/09885c04d73f4d858f23a68962cdcc72e899d260)) +* round up for _getAmountIn ([498441f](https://github.com/VenusProtocol/protocol-reserve/commit/498441f21f92d38cb68bb76f3269cb38758e5ce1)) +* round-up condition suggested by certik ([5486b99](https://github.com/VenusProtocol/protocol-reserve/commit/5486b9909b5d1a2257b8ac7287509e4cd697cd2b)) +* spelling ([a3bd0b8](https://github.com/VenusProtocol/protocol-reserve/commit/a3bd0b8e5073410adbc426034cd6cf42a6043e5e)) + ## [1.5.0-dev.3](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.2...v1.5.0-dev.3) (2024-02-27) diff --git a/package.json b/package.json index a5e5db89..b681560d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@venusprotocol/protocol-reserve", "description": "Venus Protocol contracts to manage the income generated by the protocol", - "version": "1.5.0-dev.3", + "version": "1.5.0-dev.4", "author": "Venus", "engines": { "node": ">=18.0.0" From 86aa033f39c129ac283a8c186d3a25390d1db86e Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Tue, 5 Mar 2024 14:45:47 +0000 Subject: [PATCH 39/53] chore(release): 1.5.0-dev.5 [skip ci] ## [1.5.0-dev.5](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.4...v1.5.0-dev.5) (2024-03-05) ### Features * psr deployments on ethereum ([9591482](https://github.com/VenusProtocol/protocol-reserve/commit/9591482b639fc6be0b61cfc19877cefb4da376e4)) * updating deployment files ([9068f88](https://github.com/VenusProtocol/protocol-reserve/commit/9068f8846b583885136bf7ce251261219b12e13f)) --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e78e3a9..36d081c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [1.5.0-dev.5](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.4...v1.5.0-dev.5) (2024-03-05) + + +### Features + +* psr deployments on ethereum ([9591482](https://github.com/VenusProtocol/protocol-reserve/commit/9591482b639fc6be0b61cfc19877cefb4da376e4)) +* updating deployment files ([9068f88](https://github.com/VenusProtocol/protocol-reserve/commit/9068f8846b583885136bf7ce251261219b12e13f)) + ## [1.5.0-dev.4](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.3...v1.5.0-dev.4) (2024-03-05) diff --git a/package.json b/package.json index 5929735c..04e657db 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@venusprotocol/protocol-reserve", "description": "Venus Protocol contracts to manage the income generated by the protocol", - "version": "1.5.0-dev.4", + "version": "1.5.0-dev.5", "author": "Venus", "engines": { "node": ">=18.0.0" From 558b425e71dc1a80cfae85ce501190797c5101fa Mon Sep 17 00:00:00 2001 From: 0xlucian <0xluciandev@gmail.com> Date: Thu, 29 Feb 2024 09:11:57 +0200 Subject: [PATCH 40/53] chore: add opbnbmainnet external deployments in config --- hardhat.config.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hardhat.config.ts b/hardhat.config.ts index 3a9083d1..a75463ff 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -37,6 +37,12 @@ const externalDeployments = { "node_modules/@venusprotocol/oracle/deployments/bscmainnet", "node_modules/@venusprotocol/isolated-pools/deployments/bscmainnet", ], + opbnbmainnet: [ + "node_modules/@venusprotocol/venus-protocol/deployments/opbnbmainnet", + "node_modules/@venusprotocol/governance-contracts/deployments/opbnbmainnet", + "node_modules/@venusprotocol/oracle/deployments/opbnbmainnet", + "node_modules/@venusprotocol/isolated-pools/deployments/opbnbmainnet", + ], }; extendConfig((config: HardhatConfig) => { From 6d299a73aa002a895b528e3e0324f4202b28ea42 Mon Sep 17 00:00:00 2001 From: 0xlucian <0xluciandev@gmail.com> Date: Thu, 29 Feb 2024 09:12:24 +0200 Subject: [PATCH 41/53] chore: add PSR deployment on opbnbmainnet --- deployments/opbnbmainnet/.chainId | 1 + .../opbnbmainnet/DefaultProxyAdmin.json | 257 ++++ .../opbnbmainnet/ProtocolShareReserve.json | 1059 ++++++++++++++ .../ProtocolShareReserve_Implementation.json | 1280 +++++++++++++++++ .../ProtocolShareReserve_Proxy.json | 277 ++++ .../0e89febeebc7444140de8e67c9067d2c.json | 78 + .../6da26d3137c108aa956c278f90b592e2.json | 228 +++ 7 files changed, 3180 insertions(+) create mode 100644 deployments/opbnbmainnet/.chainId create mode 100644 deployments/opbnbmainnet/DefaultProxyAdmin.json create mode 100644 deployments/opbnbmainnet/ProtocolShareReserve.json create mode 100644 deployments/opbnbmainnet/ProtocolShareReserve_Implementation.json create mode 100644 deployments/opbnbmainnet/ProtocolShareReserve_Proxy.json create mode 100644 deployments/opbnbmainnet/solcInputs/0e89febeebc7444140de8e67c9067d2c.json create mode 100644 deployments/opbnbmainnet/solcInputs/6da26d3137c108aa956c278f90b592e2.json diff --git a/deployments/opbnbmainnet/.chainId b/deployments/opbnbmainnet/.chainId new file mode 100644 index 00000000..cbd6012b --- /dev/null +++ b/deployments/opbnbmainnet/.chainId @@ -0,0 +1 @@ +204 \ No newline at end of file diff --git a/deployments/opbnbmainnet/DefaultProxyAdmin.json b/deployments/opbnbmainnet/DefaultProxyAdmin.json new file mode 100644 index 00000000..57a59887 --- /dev/null +++ b/deployments/opbnbmainnet/DefaultProxyAdmin.json @@ -0,0 +1,257 @@ +{ + "address": "0xF77bD1D893F67b3EB2Cd256239c98Ba3F238fb52", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "transactionHash": "0x6f5ff5936ce3f5d1814c53cb3358b4e3067d65a516d478dd1237c938bb8655b8", + "receipt": { + "to": null, + "from": "0x4a32670436a8A662E75E64B91B3Ab989B8a00064", + "contractAddress": "0xF77bD1D893F67b3EB2Cd256239c98Ba3F238fb52", + "transactionIndex": 1, + "gasUsed": "643983", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000002000000000000000000000000000000000000000000000000000000000000000000000080000000000000002000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000020000000000", + "blockHash": "0xba81734f171082bd28bbc9a0d472a2b8e8e543d688bac1c61e5094ec8ca9f461", + "transactionHash": "0x6f5ff5936ce3f5d1814c53cb3358b4e3067d65a516d478dd1237c938bb8655b8", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 11140997, + "transactionHash": "0x6f5ff5936ce3f5d1814c53cb3358b4e3067d65a516d478dd1237c938bb8655b8", + "address": "0xF77bD1D893F67b3EB2Cd256239c98Ba3F238fb52", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000c46796a21a3a9fab6546af3434f2ebffd0604207" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xba81734f171082bd28bbc9a0d472a2b8e8e543d688bac1c61e5094ec8ca9f461" + } + ], + "blockNumber": 11140997, + "cumulativeGasUsed": "690872", + "status": 1, + "byzantium": true + }, + "args": ["0xC46796a21a3A9FAB6546aF3434F2eBfFd0604207"], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"initialOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeProxyAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"getProxyAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"getProxyImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"upgrade\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\",\"kind\":\"dev\",\"methods\":{\"changeProxyAdmin(address,address)\":{\"details\":\"Changes the admin of `proxy` to `newAdmin`. Requirements: - This contract must be the current admin of `proxy`.\"},\"getProxyAdmin(address)\":{\"details\":\"Returns the current admin of `proxy`. Requirements: - This contract must be the admin of `proxy`.\"},\"getProxyImplementation(address)\":{\"details\":\"Returns the current implementation of `proxy`. Requirements: - This contract must be the admin of `proxy`.\"},\"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.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgrade(address,address)\":{\"details\":\"Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. Requirements: - This contract must be the admin of `proxy`.\"},\"upgradeAndCall(address,address,bytes)\":{\"details\":\"Upgrades `proxy` to `implementation` and calls a function on the new implementation. See {TransparentUpgradeableProxy-upgradeToAndCall}. Requirements: - This contract must be the admin of `proxy`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol\":\"ProxyAdmin\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/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 (address initialOwner) {\\n _transferOwnership(initialOwner);\\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\":\"0x9b2bbba5bb04f53f277739c1cdff896ba8b3bf591cfc4eab2098c655e8ac251e\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./TransparentUpgradeableProxy.sol\\\";\\nimport \\\"../../access/Ownable.sol\\\";\\n\\n/**\\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\\n */\\ncontract ProxyAdmin is Ownable {\\n\\n constructor (address initialOwner) Ownable(initialOwner) {}\\n\\n /**\\n * @dev Returns the current implementation of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"implementation()\\\")) == 0x5c60da1b\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"5c60da1b\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Returns the current admin of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"admin()\\\")) == 0xf851a440\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"f851a440\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Changes the admin of `proxy` to `newAdmin`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the current admin of `proxy`.\\n */\\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\\n proxy.changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\\n proxy.upgradeTo(implementation);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgradeAndCall(\\n TransparentUpgradeableProxy proxy,\\n address implementation,\\n bytes memory data\\n ) public payable virtual onlyOwner {\\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\\n }\\n}\\n\",\"keccak256\":\"0x754888b9c9ab5525343460b0a4fa2e2f4fca9b6a7e0e7ddea4154e2b1182a45d\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/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\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50604051610b17380380610b1783398101604081905261002f91610090565b8061003981610040565b50506100c0565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100a257600080fd5b81516001600160a01b03811681146100b957600080fd5b9392505050565b610a48806100cf6000396000f3fe60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461012b57806399a88ec41461013e578063f2fde38b1461015e578063f3b7dead1461017e57600080fd5b8063204e1c7a14610080578063715018a6146100c95780637eff275e146100e05780638da5cb5b14610100575b600080fd5b34801561008c57600080fd5b506100a061009b3660046107e4565b61019e565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100de610255565b005b3480156100ec57600080fd5b506100de6100fb366004610808565b6102e7565b34801561010c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100a0565b6100de610139366004610870565b6103ee565b34801561014a57600080fd5b506100de610159366004610808565b6104fc565b34801561016a57600080fd5b506100de6101793660046107e4565b6105d1565b34801561018a57600080fd5b506100a06101993660046107e4565b610701565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610225576040519150601f19603f3d011682016040523d82523d6000602084013e61022a565b606091505b50915091508161023957600080fd5b8080602001905181019061024d9190610964565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6102e5600061074d565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b600060405180830381600087803b1580156103d257600080fd5b505af11580156103e6573d6000803e3d6000fd5b505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461046f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef2869034906104c59086908690600401610981565b6000604051808303818588803b1580156104de57600080fd5b505af11580156104f2573d6000803e3d6000fd5b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461057d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016103b8565b60005473ffffffffffffffffffffffffffffffffffffffff163314610652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b73ffffffffffffffffffffffffffffffffffffffff81166106f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102d2565b6106fe8161074d565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146106fe57600080fd5b6000602082840312156107f657600080fd5b8135610801816107c2565b9392505050565b6000806040838503121561081b57600080fd5b8235610826816107c2565b91506020830135610836816107c2565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561088557600080fd5b8335610890816107c2565b925060208401356108a0816107c2565b9150604084013567ffffffffffffffff808211156108bd57600080fd5b818601915086601f8301126108d157600080fd5b8135818111156108e3576108e3610841565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561092957610929610841565b8160405282815289602084870101111561094257600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561097657600080fd5b8151610801816107c2565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b818110156109cb578581018301518582016060015282016109af565b818111156109dd576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160600194935050505056fea2646970667358221220bd6c09ab03bfaf9ec60a4bf8cd98903cecb891974e17e2d76a3b2002c97eeb8964736f6c634300080a0033", + "deployedBytecode": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461012b57806399a88ec41461013e578063f2fde38b1461015e578063f3b7dead1461017e57600080fd5b8063204e1c7a14610080578063715018a6146100c95780637eff275e146100e05780638da5cb5b14610100575b600080fd5b34801561008c57600080fd5b506100a061009b3660046107e4565b61019e565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100de610255565b005b3480156100ec57600080fd5b506100de6100fb366004610808565b6102e7565b34801561010c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100a0565b6100de610139366004610870565b6103ee565b34801561014a57600080fd5b506100de610159366004610808565b6104fc565b34801561016a57600080fd5b506100de6101793660046107e4565b6105d1565b34801561018a57600080fd5b506100a06101993660046107e4565b610701565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610225576040519150601f19603f3d011682016040523d82523d6000602084013e61022a565b606091505b50915091508161023957600080fd5b8080602001905181019061024d9190610964565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6102e5600061074d565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b600060405180830381600087803b1580156103d257600080fd5b505af11580156103e6573d6000803e3d6000fd5b505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461046f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef2869034906104c59086908690600401610981565b6000604051808303818588803b1580156104de57600080fd5b505af11580156104f2573d6000803e3d6000fd5b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461057d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016103b8565b60005473ffffffffffffffffffffffffffffffffffffffff163314610652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d2565b73ffffffffffffffffffffffffffffffffffffffff81166106f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102d2565b6106fe8161074d565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146106fe57600080fd5b6000602082840312156107f657600080fd5b8135610801816107c2565b9392505050565b6000806040838503121561081b57600080fd5b8235610826816107c2565b91506020830135610836816107c2565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561088557600080fd5b8335610890816107c2565b925060208401356108a0816107c2565b9150604084013567ffffffffffffffff808211156108bd57600080fd5b818601915086601f8301126108d157600080fd5b8135818111156108e3576108e3610841565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561092957610929610841565b8160405282815289602084870101111561094257600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561097657600080fd5b8151610801816107c2565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b818110156109cb578581018301518582016060015282016109af565b818111156109dd576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160600194935050505056fea2646970667358221220bd6c09ab03bfaf9ec60a4bf8cd98903cecb891974e17e2d76a3b2002c97eeb8964736f6c634300080a0033", + "devdoc": { + "details": "This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.", + "kind": "dev", + "methods": { + "changeProxyAdmin(address,address)": { + "details": "Changes the admin of `proxy` to `newAdmin`. Requirements: - This contract must be the current admin of `proxy`." + }, + "getProxyAdmin(address)": { + "details": "Returns the current admin of `proxy`. Requirements: - This contract must be the admin of `proxy`." + }, + "getProxyImplementation(address)": { + "details": "Returns the current implementation of `proxy`. Requirements: - This contract must be the admin of `proxy`." + }, + "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." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgrade(address,address)": { + "details": "Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. Requirements: - This contract must be the admin of `proxy`." + }, + "upgradeAndCall(address,address,bytes)": { + "details": "Upgrades `proxy` to `implementation` and calls a function on the new implementation. See {TransparentUpgradeableProxy-upgradeToAndCall}. Requirements: - This contract must be the admin of `proxy`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} diff --git a/deployments/opbnbmainnet/ProtocolShareReserve.json b/deployments/opbnbmainnet/ProtocolShareReserve.json new file mode 100644 index 00000000..5b96ae49 --- /dev/null +++ b/deployments/opbnbmainnet/ProtocolShareReserve.json @@ -0,0 +1,1059 @@ +{ + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "percent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "oldPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPoolRegistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" + } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" + } + ], + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolRegistry", + "type": "address" + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ], + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "receipt": { + "to": null, + "from": "0xbD9c573ABD3ec5813cE0BF58b9aF57Fb30Bc7fB9", + "contractAddress": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "transactionIndex": 15, + "gasUsed": "842879", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000002000001000000000000040000000000000000000000020000000000000000000800000000800200000100000000000000400000000001000000000000000000000000000000000080000000000000800000000000000000000001002000000400000000001000800000000000000000000000000020000000000000000001040004000000000400000000000000000020000000000200000000000000008000000000004800000000000000000000000000", + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b", + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "logs": [ + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000da1675801de412da298dc380ca530e1bede02fd0" + ], + "data": "0x", + "logIndex": 22, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + }, + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000bd9c573abd3ec5813ce0bf58b9af57fb30bc7fb9" + ], + "data": "0x", + "logIndex": 23, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + }, + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a60deae5344f1152426ca440fb6552ea0e3005d6", + "logIndex": 24, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + }, + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014", + "logIndex": 25, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + }, + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 26, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + }, + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f77bd1d893f67b3eb2cd256239c98ba3f238fb52", + "logIndex": 27, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + } + ], + "blockNumber": 17382161, + "cumulativeGasUsed": "1833382", + "status": 1, + "byzantium": true + }, + "args": [ + "0xdA1675801de412da298Dc380CA530E1BeDe02fd0", + "0xF77bD1D893F67b3EB2Cd256239c98Ba3F238fb52", + "0xcd6dc687000000000000000000000000a60deae5344f1152426ca440fb6552ea0e3005d60000000000000000000000000000000000000000000000000000000000000014" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "execute": { + "methodName": "initialize", + "args": ["0xA60Deae5344F1152426cA440fb6552eA0e3005D6", 20] + }, + "implementation": "0xdA1675801de412da298Dc380CA530E1BeDe02fd0", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/opbnbmainnet/ProtocolShareReserve_Implementation.json b/deployments/opbnbmainnet/ProtocolShareReserve_Implementation.json new file mode 100644 index 00000000..14797753 --- /dev/null +++ b/deployments/opbnbmainnet/ProtocolShareReserve_Implementation.json @@ -0,0 +1,1280 @@ +{ + "address": "0xdA1675801de412da298Dc380CA530E1BeDe02fd0", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_corePoolComptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "_wbnb", + "type": "address" + }, + { + "internalType": "address", + "name": "_vbnb", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "percent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "oldPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPoolRegistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" + } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" + } + ], + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolRegistry", + "type": "address" + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xf4c7d4c2c9ea6d569d45aaa1e32d4d880fa277dce53ddc14924b84a46b0886df", + "receipt": { + "to": null, + "from": "0xbD9c573ABD3ec5813cE0BF58b9aF57Fb30Bc7fB9", + "contractAddress": "0xdA1675801de412da298Dc380CA530E1BeDe02fd0", + "transactionIndex": 28, + "gasUsed": "2586541", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000400000000000000100000000000040000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000", + "blockHash": "0xc7ab159d43dec579535d706710e1fb51c157b848b7ca7c2f3d9b9a2bab54fb86", + "transactionHash": "0xf4c7d4c2c9ea6d569d45aaa1e32d4d880fa277dce53ddc14924b84a46b0886df", + "logs": [ + { + "transactionIndex": 28, + "blockNumber": 17382148, + "transactionHash": "0xf4c7d4c2c9ea6d569d45aaa1e32d4d880fa277dce53ddc14924b84a46b0886df", + "address": "0xdA1675801de412da298Dc380CA530E1BeDe02fd0", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", + "logIndex": 40, + "blockHash": "0xc7ab159d43dec579535d706710e1fb51c157b848b7ca7c2f3d9b9a2bab54fb86" + } + ], + "blockNumber": 17382148, + "cumulativeGasUsed": "4285821", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000001" + ], + "numDeployments": 1, + "solcInputHash": "6da26d3137c108aa956c278f90b592e2", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_corePoolComptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_wbnb\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_vbnb\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTotalPercentage\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AssetReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IProtocolShareReserve.IncomeType\",\"name\":\"incomeType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"}],\"name\":\"AssetsReservesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"percentage\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"}],\"name\":\"DistributionConfigAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"percentage\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"}],\"name\":\"DistributionConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"oldPercentage\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"newPercentage\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"}],\"name\":\"DistributionConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPoolRegistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPoolRegistry\",\"type\":\"address\"}],\"name\":\"PoolRegistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"ReservesUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_COMPTROLLER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_PERCENT\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WBNB\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"internalType\":\"uint16\",\"name\":\"percentage\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"internalType\":\"struct ProtocolShareReserve.DistributionConfig[]\",\"name\":\"configs\",\"type\":\"tuple[]\"}],\"name\":\"addOrUpdateDistributionConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"distributionTargets\",\"outputs\":[{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"internalType\":\"uint16\",\"name\":\"percentage\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"}],\"name\":\"getPercentageDistribution\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getUnreleasedFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_accessControlManager\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_loopsLimit\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLoopsLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"assets\",\"type\":\"address[]\"}],\"name\":\"releaseFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum ProtocolShareReserve.Schema\",\"name\":\"schema\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"removeDistributionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_poolRegistry\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"totalAssetReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalDistributions\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"enum IProtocolShareReserve.IncomeType\",\"name\":\"incomeType\",\"type\":\"uint8\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vBNB\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"addOrUpdateDistributionConfigs((uint8,uint16,address)[])\":{\"details\":\"Add or update destination targets based on destination address\",\"params\":{\"configs\":\"configurations of the destinations.\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"getPercentageDistribution(address,uint8)\":{\"details\":\"Used to find out the percentage distribution for a particular destination based on schema\",\"params\":{\"destination\":\"the destination address of the distribution target\",\"schema\":\"the schema of the distribution target\"},\"returns\":{\"_0\":\"percentage percentage distribution\"}},\"getUnreleasedFunds(address,uint8,address,address)\":{\"details\":\"Used to find out the amount of funds that's going to be released when release funds is called.\",\"params\":{\"asset\":\"the asset address which will be released\",\"comptroller\":\"the comptroller address of the pool\",\"destination\":\"the destination address of the distribution target\",\"schema\":\"the schema of the distribution target\"}},\"initialize(address,uint256)\":{\"details\":\"Initializes the deployer to owner.\",\"params\":{\"_accessControlManager\":\"The address of ACM contract\",\"_loopsLimit\":\"Limit for the loops in the contract to avoid DOS\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"releaseFunds(address,address[])\":{\"details\":\"Release funds\",\"params\":{\"assets\":\"assets to be released to distribution targets\",\"comptroller\":\"the comptroller address of the pool\"}},\"removeDistributionConfig(uint8,address)\":{\"details\":\"Remove destionation target if percentage is 0\",\"params\":{\"destination\":\"destination address of the configuration\",\"schema\":\"schema of the configuration\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"details\":\"Pool registry setter.\",\"params\":{\"_poolRegistry\":\"Address of the pool registry\"}},\"totalDistributions()\":{\"details\":\"Returns the total number of distribution targets\"},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"updateAssetsState(address,address,uint8)\":{\"details\":\"Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\",\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address (pool)\",\"incomeType\":\"type of income\"}}},\"stateVariables\":{\"CORE_POOL_COMPTROLLER\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"WBNB\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"},\"vBNB\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"}},\"version\":1},\"userdoc\":{\"errors\":{\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetReleased(address,address,uint8,uint256,uint256)\":{\"notice\":\"Event emitted when an asset is released to a target\"},\"AssetsReservesUpdated(address,address,uint256,uint8,uint8)\":{\"notice\":\"Event emitted after updating of the assets reserves.\"},\"DistributionConfigAdded(address,uint16,uint8)\":{\"notice\":\"Event emitted when distribution configuration is added\"},\"DistributionConfigRemoved(address,uint16,uint8)\":{\"notice\":\"Event emitted when distribution configuration is removed\"},\"DistributionConfigUpdated(address,uint16,uint16,uint8)\":{\"notice\":\"Event emitted when distribution configuration is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ReservesUpdated(address,address,uint8,uint256,uint256)\":{\"notice\":\"Event emitted when asset reserves state is updated\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_COMPTROLLER()\":{\"notice\":\"address of core pool comptroller contract\"},\"WBNB()\":{\"notice\":\"address of WBNB contract\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"assetsReserves(address,address,uint8)\":{\"notice\":\"comptroller => asset => schema => balance\"},\"distributionTargets(uint256)\":{\"notice\":\"configuration for different income distribution targets\"},\"poolRegistry()\":{\"notice\":\"address of pool registry contract\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"totalAssetReserve(address)\":{\"notice\":\"asset => balance\"},\"vBNB()\":{\"notice\":\"address of vBNB contract\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ProtocolReserve/ProtocolShareReserve.sol\":\"ProtocolShareReserve\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title MaxLoopsLimitHelper\\n * @author Venus\\n * @notice Abstract contract used to avoid collection with too many items that would generate gas errors and DoS.\\n */\\nabstract contract MaxLoopsLimitHelper {\\n // Limit for the loops to avoid the DOS\\n uint256 public maxLoopsLimit;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when max loops limit is set\\n event MaxLoopsLimitUpdated(uint256 oldMaxLoopsLimit, uint256 newmaxLoopsLimit);\\n\\n /// @notice Thrown an error on maxLoopsLimit exceeds for any loop\\n error MaxLoopsLimitExceeded(uint256 loopsLimit, uint256 requiredLoops);\\n\\n /**\\n * @notice Set the limit for the loops can iterate to avoid the DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function _setMaxLoopsLimit(uint256 limit) internal {\\n require(limit > maxLoopsLimit, \\\"Comptroller: Invalid maxLoopsLimit\\\");\\n\\n uint256 oldMaxLoopsLimit = maxLoopsLimit;\\n maxLoopsLimit = limit;\\n\\n emit MaxLoopsLimitUpdated(oldMaxLoopsLimit, limit);\\n }\\n\\n /**\\n * @notice Compare the maxLoopsLimit with number of the times loop iterate\\n * @param len Length of the loops iterate\\n * @custom:error MaxLoopsLimitExceeded error is thrown when loops length exceeds maxLoopsLimit\\n */\\n function _ensureMaxLoops(uint256 len) internal view {\\n if (len > maxLoopsLimit) {\\n revert MaxLoopsLimitExceeded(maxLoopsLimit, len);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98c97af128677629375ca93e8d8ca3f337a4abf9304a0a4ddaea9d96cc554c3b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IComptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IComptroller {\\n function isComptroller() external view returns (bool);\\n\\n function markets(address) external view returns (bool);\\n\\n function getAllMarkets() external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x7d85db8d34103352b25f29f591c1e45159222f0d2bbafaa3fcd42f42bf9a523d\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IIncomeDestination.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IIncomeDestination {\\n function updateAssetsState(address comptroller, address asset) external;\\n}\\n\",\"keccak256\":\"0xd04c051f6aaa914193353843e2d7080a7dcb88dfca2a7ce1612b0b0849cbe49d\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IPoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IPoolRegistry {\\n /// @notice Get VToken in the Pool for an Asset\\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\\n\\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb38a3b61926e55588096e0657b758b178130386143a5658030d659038ec7075c\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0xe1267c8d6c024414f636bfac1c0cb166504f7ba420341bb5d474a27f1c77e136\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IVToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IVToken {\\n function underlying() external view returns (address);\\n}\\n\",\"keccak256\":\"0x0718e50835da441b2dddcf6d52a671c43d386b96dbcc9eb41d68c3647b82c117\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/ProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { IProtocolShareReserve } from \\\"../Interfaces/IProtocolShareReserve.sol\\\";\\nimport { IComptroller } from \\\"../Interfaces/IComptroller.sol\\\";\\nimport { IPoolRegistry } from \\\"../Interfaces/IPoolRegistry.sol\\\";\\nimport { IVToken } from \\\"../Interfaces/IVToken.sol\\\";\\nimport { IIncomeDestination } from \\\"../Interfaces/IIncomeDestination.sol\\\";\\n\\nerror InvalidAddress();\\nerror UnsupportedAsset();\\nerror InvalidTotalPercentage();\\nerror InvalidMaxLoopsLimit();\\n\\ncontract ProtocolShareReserve is\\n AccessControlledV8,\\n ReentrancyGuardUpgradeable,\\n MaxLoopsLimitHelper,\\n IProtocolShareReserve\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice protocol income is categorized into two schemas.\\n /// The first schema is for spread income\\n /// The second schema is for liquidation income\\n enum Schema {\\n PROTOCOL_RESERVES,\\n ADDITIONAL_REVENUE\\n }\\n\\n struct DistributionConfig {\\n Schema schema;\\n /// @dev percenatge is represented without any scale\\n uint16 percentage;\\n address destination;\\n }\\n\\n /// @notice address of core pool comptroller contract\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable CORE_POOL_COMPTROLLER;\\n\\n /// @notice address of WBNB contract\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable WBNB;\\n\\n /// @notice address of vBNB contract\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable vBNB;\\n\\n /// @notice address of pool registry contract\\n address public poolRegistry;\\n\\n uint16 public constant MAX_PERCENT = 1e4;\\n\\n /// @notice comptroller => asset => schema => balance\\n mapping(address => mapping(address => mapping(Schema => uint256))) public assetsReserves;\\n\\n /// @notice asset => balance\\n mapping(address => uint256) public totalAssetReserve;\\n\\n /// @notice configuration for different income distribution targets\\n DistributionConfig[] public distributionTargets;\\n\\n /// @notice Emitted when pool registry address is updated\\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\\n\\n /// @notice Event emitted after updating of the assets reserves.\\n event AssetsReservesUpdated(\\n address indexed comptroller,\\n address indexed asset,\\n uint256 amount,\\n IncomeType incomeType,\\n Schema schema\\n );\\n\\n /// @notice Event emitted when an asset is released to a target\\n event AssetReleased(\\n address indexed destination,\\n address indexed asset,\\n Schema schema,\\n uint256 percent,\\n uint256 amount\\n );\\n\\n /// @notice Event emitted when asset reserves state is updated\\n event ReservesUpdated(\\n address indexed comptroller,\\n address indexed asset,\\n Schema schema,\\n uint256 oldBalance,\\n uint256 newBalance\\n );\\n\\n /// @notice Event emitted when distribution configuration is updated\\n event DistributionConfigUpdated(\\n address indexed destination,\\n uint16 oldPercentage,\\n uint16 newPercentage,\\n Schema schema\\n );\\n\\n /// @notice Event emitted when distribution configuration is added\\n event DistributionConfigAdded(address indexed destination, uint16 percentage, Schema schema);\\n\\n /// @notice Event emitted when distribution configuration is removed\\n event DistributionConfigRemoved(address indexed destination, uint16 percentage, Schema schema);\\n\\n /**\\n * @dev Constructor to initialize the immutable variables\\n * @param _corePoolComptroller The address of core pool comptroller\\n * @param _wbnb The address of WBNB\\n * @param _vbnb The address of vBNB\\n */\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n address _corePoolComptroller,\\n address _wbnb,\\n address _vbnb\\n ) {\\n ensureNonzeroAddress(_corePoolComptroller);\\n ensureNonzeroAddress(_wbnb);\\n ensureNonzeroAddress(_vbnb);\\n\\n CORE_POOL_COMPTROLLER = _corePoolComptroller;\\n WBNB = _wbnb;\\n vBNB = _vbnb;\\n\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @dev Initializes the deployer to owner.\\n * @param _accessControlManager The address of ACM contract\\n * @param _loopsLimit Limit for the loops in the contract to avoid DOS\\n */\\n function initialize(address _accessControlManager, uint256 _loopsLimit) external initializer {\\n __AccessControlled_init(_accessControlManager);\\n __ReentrancyGuard_init();\\n _setMaxLoopsLimit(_loopsLimit);\\n }\\n\\n /**\\n * @dev Pool registry setter.\\n * @param _poolRegistry Address of the pool registry\\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n */\\n function setPoolRegistry(address _poolRegistry) external onlyOwner {\\n ensureNonzeroAddress(_poolRegistry);\\n emit PoolRegistryUpdated(poolRegistry, _poolRegistry);\\n poolRegistry = _poolRegistry;\\n }\\n\\n /**\\n * @dev Add or update destination targets based on destination address\\n * @param configs configurations of the destinations.\\n */\\n function addOrUpdateDistributionConfigs(DistributionConfig[] calldata configs) external nonReentrant {\\n _checkAccessAllowed(\\\"addOrUpdateDistributionConfigs(DistributionConfig[])\\\");\\n\\n for (uint256 i = 0; i < configs.length; ) {\\n DistributionConfig memory _config = configs[i];\\n ensureNonzeroAddress(_config.destination);\\n\\n bool updated = false;\\n uint256 distributionTargetsLength = distributionTargets.length;\\n for (uint256 j = 0; j < distributionTargetsLength; ) {\\n DistributionConfig storage config = distributionTargets[j];\\n\\n if (_config.schema == config.schema && config.destination == _config.destination) {\\n emit DistributionConfigUpdated(\\n _config.destination,\\n config.percentage,\\n _config.percentage,\\n _config.schema\\n );\\n config.percentage = _config.percentage;\\n updated = true;\\n break;\\n }\\n\\n unchecked {\\n ++j;\\n }\\n }\\n\\n if (!updated) {\\n distributionTargets.push(_config);\\n emit DistributionConfigAdded(_config.destination, _config.percentage, _config.schema);\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n _ensurePercentages();\\n _ensureMaxLoops(distributionTargets.length);\\n }\\n\\n /**\\n * @dev Remove destionation target if percentage is 0\\n * @param schema schema of the configuration\\n * @param destination destination address of the configuration\\n */\\n function removeDistributionConfig(Schema schema, address destination) external {\\n _checkAccessAllowed(\\\"removeDistributionConfig(Schema,address)\\\");\\n\\n uint256 distributionIndex;\\n bool found = false;\\n for (uint256 i = 0; i < distributionTargets.length; ) {\\n DistributionConfig storage config = distributionTargets[i];\\n\\n if (schema == config.schema && destination == config.destination && config.percentage == 0) {\\n found = true;\\n distributionIndex = i;\\n break;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n if (found) {\\n emit DistributionConfigRemoved(\\n distributionTargets[distributionIndex].destination,\\n distributionTargets[distributionIndex].percentage,\\n distributionTargets[distributionIndex].schema\\n );\\n\\n distributionTargets[distributionIndex] = distributionTargets[distributionTargets.length - 1];\\n distributionTargets.pop();\\n }\\n\\n _ensurePercentages();\\n }\\n\\n /**\\n * @dev Release funds\\n * @param comptroller the comptroller address of the pool\\n * @param assets assets to be released to distribution targets\\n */\\n function releaseFunds(address comptroller, address[] calldata assets) external nonReentrant {\\n for (uint256 i = 0; i < assets.length; ) {\\n _releaseFund(comptroller, assets[i]);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @dev Used to find out the amount of funds that's going to be released when release funds is called.\\n * @param comptroller the comptroller address of the pool\\n * @param schema the schema of the distribution target\\n * @param destination the destination address of the distribution target\\n * @param asset the asset address which will be released\\n */\\n function getUnreleasedFunds(\\n address comptroller,\\n Schema schema,\\n address destination,\\n address asset\\n ) external view returns (uint256) {\\n uint256 distributionTargetsLength = distributionTargets.length;\\n for (uint256 i = 0; i < distributionTargetsLength; ) {\\n DistributionConfig storage _config = distributionTargets[i];\\n if (_config.schema == schema && _config.destination == destination) {\\n uint256 total = assetsReserves[comptroller][asset][schema];\\n return (total * _config.percentage) / MAX_PERCENT;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the total number of distribution targets\\n */\\n function totalDistributions() external view returns (uint256) {\\n return distributionTargets.length;\\n }\\n\\n /**\\n * @dev Used to find out the percentage distribution for a particular destination based on schema\\n * @param destination the destination address of the distribution target\\n * @param schema the schema of the distribution target\\n * @return percentage percentage distribution\\n */\\n function getPercentageDistribution(address destination, Schema schema) external view returns (uint256) {\\n uint256 distributionTargetsLength = distributionTargets.length;\\n for (uint256 i = 0; i < distributionTargetsLength; ) {\\n DistributionConfig memory config = distributionTargets[i];\\n\\n if (config.destination == destination && config.schema == schema) {\\n return config.percentage;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @dev Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\\n * @param comptroller Comptroller address (pool)\\n * @param asset Asset address.\\n * @param incomeType type of income\\n */\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) public override(IProtocolShareReserve) nonReentrant {\\n if (!IComptroller(comptroller).isComptroller()) revert InvalidAddress();\\n ensureNonzeroAddress(asset);\\n\\n if (\\n comptroller != CORE_POOL_COMPTROLLER &&\\n IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) == address(0)\\n ) revert InvalidAddress();\\n\\n Schema schema = _getSchema(incomeType);\\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\\n uint256 assetReserve = totalAssetReserve[asset];\\n\\n if (currentBalance > assetReserve) {\\n uint256 balanceDifference;\\n unchecked {\\n balanceDifference = currentBalance - assetReserve;\\n }\\n\\n assetsReserves[comptroller][asset][schema] += balanceDifference;\\n totalAssetReserve[asset] += balanceDifference;\\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference, incomeType, schema);\\n }\\n }\\n\\n /**\\n * @dev asset from a particular pool to be release to distribution targets\\n * @param comptroller Comptroller address(pool)\\n * @param asset Asset address.\\n */\\n function _releaseFund(address comptroller, address asset) internal {\\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\\n uint256[] memory schemaBalances = new uint256[](totalSchemas);\\n uint256 totalBalance;\\n for (uint256 schemaValue; schemaValue < totalSchemas; ) {\\n schemaBalances[schemaValue] = assetsReserves[comptroller][asset][Schema(schemaValue)];\\n totalBalance += schemaBalances[schemaValue];\\n\\n unchecked {\\n ++schemaValue;\\n }\\n }\\n\\n if (totalBalance == 0) {\\n return;\\n }\\n\\n uint256[] memory totalTransferAmounts = new uint256[](totalSchemas);\\n for (uint256 i = 0; i < distributionTargets.length; ) {\\n DistributionConfig memory _config = distributionTargets[i];\\n\\n uint256 transferAmount = (schemaBalances[uint256(_config.schema)] * _config.percentage) / MAX_PERCENT;\\n totalTransferAmounts[uint256(_config.schema)] += transferAmount;\\n\\n if (transferAmount != 0) {\\n IERC20Upgradeable(asset).safeTransfer(_config.destination, transferAmount);\\n IIncomeDestination(_config.destination).updateAssetsState(comptroller, asset);\\n\\n emit AssetReleased(_config.destination, asset, _config.schema, _config.percentage, transferAmount);\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256[] memory newSchemaBalances = new uint256[](totalSchemas);\\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\\n newSchemaBalances[schemaValue] = schemaBalances[schemaValue] - totalTransferAmounts[schemaValue];\\n assetsReserves[comptroller][asset][Schema(schemaValue)] = newSchemaBalances[schemaValue];\\n totalAssetReserve[asset] = totalAssetReserve[asset] - totalTransferAmounts[schemaValue];\\n\\n emit ReservesUpdated(\\n comptroller,\\n asset,\\n Schema(schemaValue),\\n schemaBalances[schemaValue],\\n newSchemaBalances[schemaValue]\\n );\\n\\n unchecked {\\n ++schemaValue;\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the schema based on income type\\n * @param incomeType type of income\\n * @return schema schema for distribution\\n */\\n function _getSchema(IncomeType incomeType) internal view returns (Schema schema) {\\n schema = Schema.ADDITIONAL_REVENUE;\\n\\n if (incomeType == IncomeType.SPREAD) {\\n schema = Schema.PROTOCOL_RESERVES;\\n }\\n }\\n\\n /**\\n * @dev This ensures that the total percentage of all the distribution targets is 100% or 0%\\n */\\n function _ensurePercentages() internal view {\\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\\n uint16[] memory totalPercentages = new uint16[](totalSchemas);\\n\\n uint256 distributionTargetsLength = distributionTargets.length;\\n for (uint256 i = 0; i < distributionTargetsLength; ) {\\n DistributionConfig memory config = distributionTargets[i];\\n totalPercentages[uint256(config.schema)] += config.percentage;\\n\\n unchecked {\\n ++i;\\n }\\n }\\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\\n if (totalPercentages[schemaValue] != MAX_PERCENT && totalPercentages[schemaValue] != 0)\\n revert InvalidTotalPercentage();\\n\\n unchecked {\\n ++schemaValue;\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the underlying asset address for the vToken\\n * @param vToken vToken address\\n * @return asset address of asset\\n */\\n function _getUnderlying(address vToken) internal view returns (address) {\\n if (vToken == vBNB) {\\n return WBNB;\\n } else {\\n return IVToken(vToken).underlying();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x18a958e20fae4e3aa04f109a69e45d3e86681f6b052bc35715f2dc3f69b35670\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162002f8738038062002f8783398101604081905262000034916200018a565b6200003f8362000081565b6200004a8262000081565b620000558162000081565b6001600160a01b0380841660805282811660a052811660c05262000078620000ac565b505050620001d4565b6001600160a01b038116620000a9576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff1615620001195760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016b576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018557600080fd5b919050565b600080600060608486031215620001a057600080fd5b620001ab846200016d565b9250620001bb602085016200016d565b9150620001cb604085016200016d565b90509250925092565b60805160a05160c051612d7c6200020b6000396000610209015260006103090152600081816103c901526104bc0152612d7c6000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c8063893ffe98116100ee578063b4a0bdf311610097578063e30c397811610071578063e30c3978146103a0578063f2fde38b146103b1578063fa7b81a0146103c4578063fc31116a146103eb57600080fd5b8063b4a0bdf314610373578063be26317e14610384578063cd6dc6871461038d57600080fd5b8063966961f0116100c8578063966961f01461032b578063aea211211461033e578063afcff50f1461035f57600080fd5b8063893ffe98146102e05780638da5cb5b146102f35780638dd950021461030457600080fd5b80634f429f3611610150578063715018a61161012a578063715018a6146102bd57806379ba5097146102c55780637b77cd6a146102cd57600080fd5b80634f429f36146102655780635db6da12146102785780635f3d6133146102aa57600080fd5b806316faecec1161018157806316faecec146101f157806333e1567f14610204578063392ee7121461024357600080fd5b80630e32cb86146101a85780631036bbe2146101bd578063163db71b146101de575b600080fd5b6101bb6101b63660046125a8565b6103fe565b005b6101c661271081565b60405161ffff90911681526020015b60405180910390f35b610130545b6040519081526020016101d5565b6101bb6101ff3660046125d9565b610412565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101d5565b610256610251366004612624565b610788565b6040516101d5939291906126a3565b6101bb6102733660046126d1565b6107c8565b6101e36102863660046125d9565b61012e60209081526000938452604080852082529284528284209052825290205481565b6101bb6102b836600461270a565b610b0a565b6101bb610e19565b6101bb610e2d565b6101bb6102db3660046125a8565b610ebd565b6101e36102ee36600461277f565b610f44565b6033546001600160a01b031661022b565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6101e36103393660046127db565b611066565b6101e361034c3660046125a8565b61012f6020526000908152604090205481565b61012d5461022b906001600160a01b031681565b6097546001600160a01b031661022b565b6101e360fb5481565b6101bb61039b366004612809565b61115b565b6065546001600160a01b031661022b565b6101bb6103bf3660046125a8565b6112e6565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6101bb6103f9366004612835565b61136f565b6104066113c5565b61040f8161141f565b50565b61041a611515565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610457573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047b91906128bd565b6104b1576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104ba8261156e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614158015610593575061012d546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015610564573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058891906128df565b6001600160a01b0316145b156105ca576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105d5826115ae565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038516906370a0823190602401602060405180830381865afa158015610638573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065c91906128fc565b6001600160a01b038516600090815261012f602052604090205490915080821115610776576001600160a01b03808716600090815261012e602090815260408083209389168352929052908120828403918291908660018111156106c2576106c261263d565b60018111156106d3576106d361263d565b815260200190815260200160002060008282546106f09190612944565b90915550506001600160a01b038616600090815261012f60205260408120805483929061071e908490612944565b92505081905550856001600160a01b0316876001600160a01b03167fa46b2431e663cf7b50c9d5129aff85d2394ecfd447b7ccba83986510a9d945ea83888860405161076c9392919061295c565b60405180910390a3505b505050610783600160c955565b505050565b610130818154811061079957600080fd5b60009182526020909120015460ff81169150610100810461ffff1690630100000090046001600160a01b031683565b6107e9604051806060016040528060288152602001612ceb602891396115d9565b600080805b61013054811015610894576000610130828154811061080f5761080f612989565b6000918252602090912001805490915060ff1660018111156108335761083361263d565b8660018111156108455761084561263d565b148015610865575080546001600160a01b03868116630100000090920416145b801561087957508054610100900461ffff16155b1561088b576001925081935050610894565b506001016107ee565b508015610afc5761013082815481106108af576108af612989565b9060005260206000200160000160039054906101000a90046001600160a01b03166001600160a01b03167f70e7a210881df49522a5bf05d477e00d59e52a41c96c1eedeaeb356b9e6c81cc610130848154811061090e5761090e612989565b9060005260206000200160000160019054906101000a900461ffff16610130858154811061093e5761093e612989565b60009182526020909120015460405161095b929160ff16906129b8565b60405180910390a26101308054610974906001906129d9565b8154811061098457610984612989565b9060005260206000200161013083815481106109a2576109a2612989565b60009182526020909120825491018054909160ff169082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183818111156109ef576109ef61263d565b02179055508154815461ffff61010092839004169091027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff82168117835592546001600160a01b0363010000009182900416027fffffffffffffffffff0000000000000000000000000000000000000000ffffff9093167fffffffffffffffffff00000000000000000000000000000000000000000000ff90911617919091179055610130805480610aa357610aa36129f0565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffff00000000000000000000000000000000000000000000001690550190555b610b046116a5565b50505050565b610b12611515565b610b33604051806060016040528060348152602001612d13603491396115d9565b60005b81811015610df5576000838383818110610b5257610b52612989565b905060600201803603810190610b689190612a4e565b9050610b77816040015161156e565b61013054600090815b81811015610ca55760006101308281548110610b9e57610b9e612989565b6000918252602090912001805490915060ff166001811115610bc257610bc261263d565b85516001811115610bd557610bd561263d565b148015610bfa575060408501518154630100000090046001600160a01b039081169116145b15610c9c5760408581015182546020880151885193516001600160a01b03909316937fa682db621f4ae1c92cd6c492151d32fe657fc6db6e87bd65eb8bda05311f6ef293610c5393610100900461ffff16929190612aee565b60405180910390a26020850151815461ffff909116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff90911617905560019250610ca5565b50600101610b80565b5081610de75761013080546001818101835560009290925284517f2f605e086faac1d93117bbfbc18835d434e9405fadc1ca66faf4b864746daf349091018054869391929183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115610d2057610d2061263d565b021790555060208281015182546040948501517fffffffffffffffffff00000000000000000000000000000000000000000000ff90911661010061ffff909316929092027fffffffffffffffffff0000000000000000000000000000000000000000ffffff169190911763010000006001600160a01b03928316021790925585830151908601518651935191909216927f8c96910d818618d8b1de4e1b5672a192443e87aa553f0ebe4c47f9d8c928b28292610dde929091906129b8565b60405180910390a25b836001019350505050610b36565b50610dfe6116a5565b61013054610e0b9061187d565b610e15600160c955565b5050565b610e216113c5565b610e2b60006118c7565b565b60655433906001600160a01b03168114610eb45760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61040f816118c7565b610ec56113c5565b610ece8161156e565b61012d546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b61013054600090815b8181101561105b5760006101308281548110610f6b57610f6b612989565b906000526020600020019050866001811115610f8957610f8961263d565b815460ff166001811115610f9f57610f9f61263d565b148015610fbf575080546001600160a01b03878116630100000090920416145b15611052576001600160a01b03808916600090815261012e60209081526040808320938916835292905290812081896001811115610fff57610fff61263d565b60018111156110105761101061263d565b815260208101919091526040016000205482549091506127109061103d90610100900461ffff1683612b0a565b6110479190612b47565b94505050505061105e565b50600101610f4d565b50505b949350505050565b61013054600090815b81811015611152576000610130828154811061108d5761108d612989565b60009182526020909120604080516060810190915291018054829060ff1660018111156110bc576110bc61263d565b60018111156110cd576110cd61263d565b81529054610100810461ffff166020830152630100000090046001600160a01b03908116604092830152908201519192508781169116148015611132575084600181111561111d5761111d61263d565b815160018111156111305761113061263d565b145b15611149576020015161ffff169250611155915050565b5060010161106f565b50505b92915050565b600054610100900460ff161580801561117b5750600054600160ff909116105b806111955750303b158015611195575060005460ff166001145b6112075760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610eab565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561126557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61126e836118f8565b611276611986565b61127f82611a0b565b801561078357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b6112ee6113c5565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556113376033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b611377611515565b60005b818110156113ba576113b28484848481811061139857611398612989565b90506020020160208101906113ad91906125a8565b611ac0565b60010161137a565b50610783600160c955565b6033546001600160a01b03163314610e2b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610eab565b6001600160a01b03811661149b5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610eab565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091015b60405180910390a15050565b600260c954036115675760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610eab565b600260c955565b6001600160a01b03811661040f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008260018111156115c4576115c461263d565b036115cd575060005b919050565b600160c955565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906116259033908690600401612bf8565b602060405180830381865afa158015611642573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166691906128bd565b905080610e15573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610eab93929190612c1a565b60006116b2600180612944565b905060008167ffffffffffffffff8111156116cf576116cf612a1f565b6040519080825280602002602001820160405280156116f8578160200160208202803683370190505b506101305490915060005b818110156117e1576000610130828154811061172157611721612989565b60009182526020909120604080516060810190915291018054829060ff1660018111156117505761175061263d565b60018111156117615761176161263d565b81529054610100810461ffff1660208084019190915263010000009091046001600160a01b0316604090920191909152810151815191925090859060018111156117ad576117ad61263d565b815181106117bd576117bd612989565b602002602001018181516117d19190612c4f565b61ffff1690525050600101611703565b5060005b83811015610b045761271061ffff1683828151811061180657611806612989565b602002602001015161ffff161415801561183e575082818151811061182d5761182d612989565b602002602001015161ffff16600014155b15611875576040517f0b8ad7f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016117e5565b60fb5481111561040f5760fb546040517ff257f636000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610eab565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561040f81612099565b600054610100900460ff166119755760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b61197d612103565b61040f81612188565b600054610100900460ff16611a035760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b612205565b60fb548111611a825760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d60448201527f69740000000000000000000000000000000000000000000000000000000000006064820152608401610eab565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa9101611509565b6000611acd600180612944565b905060008167ffffffffffffffff811115611aea57611aea612a1f565b604051908082528060200260200182016040528015611b13578160200160208202803683370190505b5090506000805b83811015611bdb576001600160a01b03808716600090815261012e60209081526040808320938916835292905290812090826001811115611b5d57611b5d61263d565b6001811115611b6e57611b6e61263d565b6001811115611b7f57611b7f61263d565b815260200190815260200160002054838281518110611ba057611ba0612989565b602002602001018181525050828181518110611bbe57611bbe612989565b602002602001015182611bd19190612944565b9150600101611b1a565b5080600003611beb575050505050565b60008367ffffffffffffffff811115611c0657611c06612a1f565b604051908082528060200260200182016040528015611c2f578160200160208202803683370190505b50905060005b61013054811015611e645760006101308281548110611c5657611c56612989565b60009182526020909120604080516060810190915291018054829060ff166001811115611c8557611c8561263d565b6001811115611c9657611c9661263d565b81529054610100810461ffff90811660208085019190915263010000009092046001600160a01b0316604090930192909252820151825192935060009261271092919091169088906001811115611cef57611cef61263d565b81518110611cff57611cff612989565b6020026020010151611d119190612b0a565b611d1b9190612b47565b9050808483600001516001811115611d3557611d3561263d565b81518110611d4557611d45612989565b60200260200101818151611d599190612944565b9052508015611e5a576040820151611d7c906001600160a01b038a169083612282565b60408083015190517faac59a750000000000000000000000000000000000000000000000000000000081526001600160a01b038b811660048301528a811660248301529091169063aac59a7590604401600060405180830381600087803b158015611de657600080fd5b505af1158015611dfa573d6000803e3d6000fd5b50505050876001600160a01b031682604001516001600160a01b03167f09f71e7b22d78540ee9a42f09917a9d62f46735cb0dfa70d6bab27866d9cb5008460000151856020015185604051611e5193929190612c75565b60405180910390a35b5050600101611c35565b5060008467ffffffffffffffff811115611e8057611e80612a1f565b604051908082528060200260200182016040528015611ea9578160200160208202803683370190505b50905060005b8581101561208f57828181518110611ec957611ec9612989565b6020026020010151858281518110611ee357611ee3612989565b6020026020010151611ef591906129d9565b828281518110611f0757611f07612989565b602002602001018181525050818181518110611f2557611f25612989565b6020908102919091018101516001600160a01b03808b16600090815261012e84526040808220928c1682529190935282209091836001811115611f6a57611f6a61263d565b6001811115611f7b57611f7b61263d565b6001811115611f8c57611f8c61263d565b815260200190815260200160002081905550828181518110611fb057611fb0612989565b602002602001015161012f6000896001600160a01b03166001600160a01b0316815260200190815260200160002054611fe991906129d9565b6001600160a01b03808916600081815261012f602052604090209290925589167f7d881f3d6246a6a2b97b121b8ba093c17497912c68e8b2bca6108528e91df3ca83600181111561203c5761203c61263d565b88858151811061204e5761204e612989565b602002602001015186868151811061206857612068612989565b602002602001015160405161207f93929190612c9a565b60405180910390a3600101611eaf565b5050505050505050565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166121805760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b612302565b600054610100900460ff166104065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b600054610100900460ff166115d25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610783908490612388565b600054610100900460ff1661237f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b336118c7565b60006123dd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124709092919063ffffffff16565b90508051600014806123fe5750808060200190518101906123fe91906128bd565b6107835760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610eab565b606061105e848460008585600080866001600160a01b031685876040516124979190612cbb565b60006040518083038185875af1925050503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b50915091506124ea878383876124f5565b979650505050505050565b6060831561256457825160000361255d576001600160a01b0385163b61255d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610eab565b508161105e565b61105e83838151156125795781518083602001fd5b8060405162461bcd60e51b8152600401610eab9190612cd7565b6001600160a01b038116811461040f57600080fd5b6000602082840312156125ba57600080fd5b81356125c581612593565b9392505050565b6002811061040f57600080fd5b6000806000606084860312156125ee57600080fd5b83356125f981612593565b9250602084013561260981612593565b91506040840135612619816125cc565b809150509250925092565b60006020828403121561263657600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061040f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b606081016126b08561266c565b93815261ffff9290921660208301526001600160a01b031660409091015290565b600080604083850312156126e457600080fd5b82356126ef816125cc565b915060208301356126ff81612593565b809150509250929050565b6000806020838503121561271d57600080fd5b823567ffffffffffffffff8082111561273557600080fd5b818501915085601f83011261274957600080fd5b81358181111561275857600080fd5b86602060608302850101111561276d57600080fd5b60209290920196919550909350505050565b6000806000806080858703121561279557600080fd5b84356127a081612593565b935060208501356127b0816125cc565b925060408501356127c081612593565b915060608501356127d081612593565b939692955090935050565b600080604083850312156127ee57600080fd5b82356127f981612593565b915060208301356126ff816125cc565b6000806040838503121561281c57600080fd5b823561282781612593565b946020939093013593505050565b60008060006040848603121561284a57600080fd5b833561285581612593565b9250602084013567ffffffffffffffff8082111561287257600080fd5b818601915086601f83011261288657600080fd5b81358181111561289557600080fd5b8760208260051b85010111156128aa57600080fd5b6020830194508093505050509250925092565b6000602082840312156128cf57600080fd5b815180151581146125c557600080fd5b6000602082840312156128f157600080fd5b81516125c581612593565b60006020828403121561290e57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561295757612957612915565b500190565b8381526060810161296c8461266c565b83602083015261297b8361266c565b826040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b61ffff83168152604081016129cc8361266c565b8260208301529392505050565b6000828210156129eb576129eb612915565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060608284031215612a6057600080fd5b6040516060810181811067ffffffffffffffff82111715612aaa577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528235612ab8816125cc565b8152602083013561ffff81168114612acf57600080fd5b60208201526040830135612ae281612593565b60408201529392505050565b61ffff8481168252831660208201526060810161297b8361266c565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612b4257612b42612915565b500290565b600082612b7d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015612b9d578181015183820152602001612b85565b83811115610b045750506000910152565b60008151808452612bc6816020860160208601612b82565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b038316815260406020820152600061105e6040830184612bae565b60006001600160a01b03808616835280851660208401525060606040830152612c466060830184612bae565b95945050505050565b600061ffff808316818516808303821115612c6c57612c6c612915565b01949350505050565b60608101612c828561266c565b93815261ffff92909216602083015260409091015290565b60608101612ca78561266c565b938152602081019290925260409091015290565b60008251612ccd818460208701612b82565b9190910192915050565b6020815260006125c56020830184612bae56fe72656d6f7665446973747269627574696f6e436f6e66696728536368656d612c61646472657373296164644f72557064617465446973747269627574696f6e436f6e6669677328446973747269627574696f6e436f6e6669675b5d29a26469706673582212205eb79a0a3612b6adb45dcbc7d14826d2afd5547af534b542b9d4ebd2e2df21cb64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a35760003560e01c8063893ffe98116100ee578063b4a0bdf311610097578063e30c397811610071578063e30c3978146103a0578063f2fde38b146103b1578063fa7b81a0146103c4578063fc31116a146103eb57600080fd5b8063b4a0bdf314610373578063be26317e14610384578063cd6dc6871461038d57600080fd5b8063966961f0116100c8578063966961f01461032b578063aea211211461033e578063afcff50f1461035f57600080fd5b8063893ffe98146102e05780638da5cb5b146102f35780638dd950021461030457600080fd5b80634f429f3611610150578063715018a61161012a578063715018a6146102bd57806379ba5097146102c55780637b77cd6a146102cd57600080fd5b80634f429f36146102655780635db6da12146102785780635f3d6133146102aa57600080fd5b806316faecec1161018157806316faecec146101f157806333e1567f14610204578063392ee7121461024357600080fd5b80630e32cb86146101a85780631036bbe2146101bd578063163db71b146101de575b600080fd5b6101bb6101b63660046125a8565b6103fe565b005b6101c661271081565b60405161ffff90911681526020015b60405180910390f35b610130545b6040519081526020016101d5565b6101bb6101ff3660046125d9565b610412565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101d5565b610256610251366004612624565b610788565b6040516101d5939291906126a3565b6101bb6102733660046126d1565b6107c8565b6101e36102863660046125d9565b61012e60209081526000938452604080852082529284528284209052825290205481565b6101bb6102b836600461270a565b610b0a565b6101bb610e19565b6101bb610e2d565b6101bb6102db3660046125a8565b610ebd565b6101e36102ee36600461277f565b610f44565b6033546001600160a01b031661022b565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6101e36103393660046127db565b611066565b6101e361034c3660046125a8565b61012f6020526000908152604090205481565b61012d5461022b906001600160a01b031681565b6097546001600160a01b031661022b565b6101e360fb5481565b6101bb61039b366004612809565b61115b565b6065546001600160a01b031661022b565b6101bb6103bf3660046125a8565b6112e6565b61022b7f000000000000000000000000000000000000000000000000000000000000000081565b6101bb6103f9366004612835565b61136f565b6104066113c5565b61040f8161141f565b50565b61041a611515565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610457573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047b91906128bd565b6104b1576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104ba8261156e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614158015610593575061012d546040517f266e0a7f0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015610564573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058891906128df565b6001600160a01b0316145b156105ca576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105d5826115ae565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038516906370a0823190602401602060405180830381865afa158015610638573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065c91906128fc565b6001600160a01b038516600090815261012f602052604090205490915080821115610776576001600160a01b03808716600090815261012e602090815260408083209389168352929052908120828403918291908660018111156106c2576106c261263d565b60018111156106d3576106d361263d565b815260200190815260200160002060008282546106f09190612944565b90915550506001600160a01b038616600090815261012f60205260408120805483929061071e908490612944565b92505081905550856001600160a01b0316876001600160a01b03167fa46b2431e663cf7b50c9d5129aff85d2394ecfd447b7ccba83986510a9d945ea83888860405161076c9392919061295c565b60405180910390a3505b505050610783600160c955565b505050565b610130818154811061079957600080fd5b60009182526020909120015460ff81169150610100810461ffff1690630100000090046001600160a01b031683565b6107e9604051806060016040528060288152602001612ceb602891396115d9565b600080805b61013054811015610894576000610130828154811061080f5761080f612989565b6000918252602090912001805490915060ff1660018111156108335761083361263d565b8660018111156108455761084561263d565b148015610865575080546001600160a01b03868116630100000090920416145b801561087957508054610100900461ffff16155b1561088b576001925081935050610894565b506001016107ee565b508015610afc5761013082815481106108af576108af612989565b9060005260206000200160000160039054906101000a90046001600160a01b03166001600160a01b03167f70e7a210881df49522a5bf05d477e00d59e52a41c96c1eedeaeb356b9e6c81cc610130848154811061090e5761090e612989565b9060005260206000200160000160019054906101000a900461ffff16610130858154811061093e5761093e612989565b60009182526020909120015460405161095b929160ff16906129b8565b60405180910390a26101308054610974906001906129d9565b8154811061098457610984612989565b9060005260206000200161013083815481106109a2576109a2612989565b60009182526020909120825491018054909160ff169082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183818111156109ef576109ef61263d565b02179055508154815461ffff61010092839004169091027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff82168117835592546001600160a01b0363010000009182900416027fffffffffffffffffff0000000000000000000000000000000000000000ffffff9093167fffffffffffffffffff00000000000000000000000000000000000000000000ff90911617919091179055610130805480610aa357610aa36129f0565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffff00000000000000000000000000000000000000000000001690550190555b610b046116a5565b50505050565b610b12611515565b610b33604051806060016040528060348152602001612d13603491396115d9565b60005b81811015610df5576000838383818110610b5257610b52612989565b905060600201803603810190610b689190612a4e565b9050610b77816040015161156e565b61013054600090815b81811015610ca55760006101308281548110610b9e57610b9e612989565b6000918252602090912001805490915060ff166001811115610bc257610bc261263d565b85516001811115610bd557610bd561263d565b148015610bfa575060408501518154630100000090046001600160a01b039081169116145b15610c9c5760408581015182546020880151885193516001600160a01b03909316937fa682db621f4ae1c92cd6c492151d32fe657fc6db6e87bd65eb8bda05311f6ef293610c5393610100900461ffff16929190612aee565b60405180910390a26020850151815461ffff909116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff90911617905560019250610ca5565b50600101610b80565b5081610de75761013080546001818101835560009290925284517f2f605e086faac1d93117bbfbc18835d434e9405fadc1ca66faf4b864746daf349091018054869391929183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115610d2057610d2061263d565b021790555060208281015182546040948501517fffffffffffffffffff00000000000000000000000000000000000000000000ff90911661010061ffff909316929092027fffffffffffffffffff0000000000000000000000000000000000000000ffffff169190911763010000006001600160a01b03928316021790925585830151908601518651935191909216927f8c96910d818618d8b1de4e1b5672a192443e87aa553f0ebe4c47f9d8c928b28292610dde929091906129b8565b60405180910390a25b836001019350505050610b36565b50610dfe6116a5565b61013054610e0b9061187d565b610e15600160c955565b5050565b610e216113c5565b610e2b60006118c7565b565b60655433906001600160a01b03168114610eb45760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61040f816118c7565b610ec56113c5565b610ece8161156e565b61012d546040516001600160a01b038084169216907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b61013054600090815b8181101561105b5760006101308281548110610f6b57610f6b612989565b906000526020600020019050866001811115610f8957610f8961263d565b815460ff166001811115610f9f57610f9f61263d565b148015610fbf575080546001600160a01b03878116630100000090920416145b15611052576001600160a01b03808916600090815261012e60209081526040808320938916835292905290812081896001811115610fff57610fff61263d565b60018111156110105761101061263d565b815260208101919091526040016000205482549091506127109061103d90610100900461ffff1683612b0a565b6110479190612b47565b94505050505061105e565b50600101610f4d565b50505b949350505050565b61013054600090815b81811015611152576000610130828154811061108d5761108d612989565b60009182526020909120604080516060810190915291018054829060ff1660018111156110bc576110bc61263d565b60018111156110cd576110cd61263d565b81529054610100810461ffff166020830152630100000090046001600160a01b03908116604092830152908201519192508781169116148015611132575084600181111561111d5761111d61263d565b815160018111156111305761113061263d565b145b15611149576020015161ffff169250611155915050565b5060010161106f565b50505b92915050565b600054610100900460ff161580801561117b5750600054600160ff909116105b806111955750303b158015611195575060005460ff166001145b6112075760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610eab565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561126557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61126e836118f8565b611276611986565b61127f82611a0b565b801561078357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b6112ee6113c5565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556113376033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b611377611515565b60005b818110156113ba576113b28484848481811061139857611398612989565b90506020020160208101906113ad91906125a8565b611ac0565b60010161137a565b50610783600160c955565b6033546001600160a01b03163314610e2b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610eab565b6001600160a01b03811661149b5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610eab565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091015b60405180910390a15050565b600260c954036115675760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610eab565b600260c955565b6001600160a01b03811661040f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008260018111156115c4576115c461263d565b036115cd575060005b919050565b600160c955565b6097546040517f18c5e8ab0000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906318c5e8ab906116259033908690600401612bf8565b602060405180830381865afa158015611642573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166691906128bd565b905080610e15573330836040517f4a3fa293000000000000000000000000000000000000000000000000000000008152600401610eab93929190612c1a565b60006116b2600180612944565b905060008167ffffffffffffffff8111156116cf576116cf612a1f565b6040519080825280602002602001820160405280156116f8578160200160208202803683370190505b506101305490915060005b818110156117e1576000610130828154811061172157611721612989565b60009182526020909120604080516060810190915291018054829060ff1660018111156117505761175061263d565b60018111156117615761176161263d565b81529054610100810461ffff1660208084019190915263010000009091046001600160a01b0316604090920191909152810151815191925090859060018111156117ad576117ad61263d565b815181106117bd576117bd612989565b602002602001018181516117d19190612c4f565b61ffff1690525050600101611703565b5060005b83811015610b045761271061ffff1683828151811061180657611806612989565b602002602001015161ffff161415801561183e575082818151811061182d5761182d612989565b602002602001015161ffff16600014155b15611875576040517f0b8ad7f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016117e5565b60fb5481111561040f5760fb546040517ff257f636000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610eab565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561040f81612099565b600054610100900460ff166119755760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b61197d612103565b61040f81612188565b600054610100900460ff16611a035760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b612205565b60fb548111611a825760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d60448201527f69740000000000000000000000000000000000000000000000000000000000006064820152608401610eab565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa9101611509565b6000611acd600180612944565b905060008167ffffffffffffffff811115611aea57611aea612a1f565b604051908082528060200260200182016040528015611b13578160200160208202803683370190505b5090506000805b83811015611bdb576001600160a01b03808716600090815261012e60209081526040808320938916835292905290812090826001811115611b5d57611b5d61263d565b6001811115611b6e57611b6e61263d565b6001811115611b7f57611b7f61263d565b815260200190815260200160002054838281518110611ba057611ba0612989565b602002602001018181525050828181518110611bbe57611bbe612989565b602002602001015182611bd19190612944565b9150600101611b1a565b5080600003611beb575050505050565b60008367ffffffffffffffff811115611c0657611c06612a1f565b604051908082528060200260200182016040528015611c2f578160200160208202803683370190505b50905060005b61013054811015611e645760006101308281548110611c5657611c56612989565b60009182526020909120604080516060810190915291018054829060ff166001811115611c8557611c8561263d565b6001811115611c9657611c9661263d565b81529054610100810461ffff90811660208085019190915263010000009092046001600160a01b0316604090930192909252820151825192935060009261271092919091169088906001811115611cef57611cef61263d565b81518110611cff57611cff612989565b6020026020010151611d119190612b0a565b611d1b9190612b47565b9050808483600001516001811115611d3557611d3561263d565b81518110611d4557611d45612989565b60200260200101818151611d599190612944565b9052508015611e5a576040820151611d7c906001600160a01b038a169083612282565b60408083015190517faac59a750000000000000000000000000000000000000000000000000000000081526001600160a01b038b811660048301528a811660248301529091169063aac59a7590604401600060405180830381600087803b158015611de657600080fd5b505af1158015611dfa573d6000803e3d6000fd5b50505050876001600160a01b031682604001516001600160a01b03167f09f71e7b22d78540ee9a42f09917a9d62f46735cb0dfa70d6bab27866d9cb5008460000151856020015185604051611e5193929190612c75565b60405180910390a35b5050600101611c35565b5060008467ffffffffffffffff811115611e8057611e80612a1f565b604051908082528060200260200182016040528015611ea9578160200160208202803683370190505b50905060005b8581101561208f57828181518110611ec957611ec9612989565b6020026020010151858281518110611ee357611ee3612989565b6020026020010151611ef591906129d9565b828281518110611f0757611f07612989565b602002602001018181525050818181518110611f2557611f25612989565b6020908102919091018101516001600160a01b03808b16600090815261012e84526040808220928c1682529190935282209091836001811115611f6a57611f6a61263d565b6001811115611f7b57611f7b61263d565b6001811115611f8c57611f8c61263d565b815260200190815260200160002081905550828181518110611fb057611fb0612989565b602002602001015161012f6000896001600160a01b03166001600160a01b0316815260200190815260200160002054611fe991906129d9565b6001600160a01b03808916600081815261012f602052604090209290925589167f7d881f3d6246a6a2b97b121b8ba093c17497912c68e8b2bca6108528e91df3ca83600181111561203c5761203c61263d565b88858151811061204e5761204e612989565b602002602001015186868151811061206857612068612989565b602002602001015160405161207f93929190612c9a565b60405180910390a3600101611eaf565b5050505050505050565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166121805760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b612302565b600054610100900460ff166104065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b600054610100900460ff166115d25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610783908490612388565b600054610100900460ff1661237f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610eab565b610e2b336118c7565b60006123dd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124709092919063ffffffff16565b90508051600014806123fe5750808060200190518101906123fe91906128bd565b6107835760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610eab565b606061105e848460008585600080866001600160a01b031685876040516124979190612cbb565b60006040518083038185875af1925050503d80600081146124d4576040519150601f19603f3d011682016040523d82523d6000602084013e6124d9565b606091505b50915091506124ea878383876124f5565b979650505050505050565b6060831561256457825160000361255d576001600160a01b0385163b61255d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610eab565b508161105e565b61105e83838151156125795781518083602001fd5b8060405162461bcd60e51b8152600401610eab9190612cd7565b6001600160a01b038116811461040f57600080fd5b6000602082840312156125ba57600080fd5b81356125c581612593565b9392505050565b6002811061040f57600080fd5b6000806000606084860312156125ee57600080fd5b83356125f981612593565b9250602084013561260981612593565b91506040840135612619816125cc565b809150509250925092565b60006020828403121561263657600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061040f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b606081016126b08561266c565b93815261ffff9290921660208301526001600160a01b031660409091015290565b600080604083850312156126e457600080fd5b82356126ef816125cc565b915060208301356126ff81612593565b809150509250929050565b6000806020838503121561271d57600080fd5b823567ffffffffffffffff8082111561273557600080fd5b818501915085601f83011261274957600080fd5b81358181111561275857600080fd5b86602060608302850101111561276d57600080fd5b60209290920196919550909350505050565b6000806000806080858703121561279557600080fd5b84356127a081612593565b935060208501356127b0816125cc565b925060408501356127c081612593565b915060608501356127d081612593565b939692955090935050565b600080604083850312156127ee57600080fd5b82356127f981612593565b915060208301356126ff816125cc565b6000806040838503121561281c57600080fd5b823561282781612593565b946020939093013593505050565b60008060006040848603121561284a57600080fd5b833561285581612593565b9250602084013567ffffffffffffffff8082111561287257600080fd5b818601915086601f83011261288657600080fd5b81358181111561289557600080fd5b8760208260051b85010111156128aa57600080fd5b6020830194508093505050509250925092565b6000602082840312156128cf57600080fd5b815180151581146125c557600080fd5b6000602082840312156128f157600080fd5b81516125c581612593565b60006020828403121561290e57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561295757612957612915565b500190565b8381526060810161296c8461266c565b83602083015261297b8361266c565b826040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b61ffff83168152604081016129cc8361266c565b8260208301529392505050565b6000828210156129eb576129eb612915565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060608284031215612a6057600080fd5b6040516060810181811067ffffffffffffffff82111715612aaa577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528235612ab8816125cc565b8152602083013561ffff81168114612acf57600080fd5b60208201526040830135612ae281612593565b60408201529392505050565b61ffff8481168252831660208201526060810161297b8361266c565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612b4257612b42612915565b500290565b600082612b7d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015612b9d578181015183820152602001612b85565b83811115610b045750506000910152565b60008151808452612bc6816020860160208601612b82565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6001600160a01b038316815260406020820152600061105e6040830184612bae565b60006001600160a01b03808616835280851660208401525060606040830152612c466060830184612bae565b95945050505050565b600061ffff808316818516808303821115612c6c57612c6c612915565b01949350505050565b60608101612c828561266c565b93815261ffff92909216602083015260409091015290565b60608101612ca78561266c565b938152602081019290925260409091015290565b60008251612ccd818460208701612b82565b9190910192915050565b6020815260006125c56020830184612bae56fe72656d6f7665446973747269627574696f6e436f6e66696728536368656d612c61646472657373296164644f72557064617465446973747269627574696f6e436f6e6669677328446973747269627574696f6e436f6e6669675b5d29a26469706673582212205eb79a0a3612b6adb45dcbc7d14826d2afd5547af534b542b9d4ebd2e2df21cb64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptOwnership()": { + "details": "The new owner accepts the ownership transfer." + }, + "addOrUpdateDistributionConfigs((uint8,uint16,address)[])": { + "details": "Add or update destination targets based on destination address", + "params": { + "configs": "configurations of the destinations." + } + }, + "constructor": { + "custom:oz-upgrades-unsafe-allow": "constructor" + }, + "getPercentageDistribution(address,uint8)": { + "details": "Used to find out the percentage distribution for a particular destination based on schema", + "params": { + "destination": "the destination address of the distribution target", + "schema": "the schema of the distribution target" + }, + "returns": { + "_0": "percentage percentage distribution" + } + }, + "getUnreleasedFunds(address,uint8,address,address)": { + "details": "Used to find out the amount of funds that's going to be released when release funds is called.", + "params": { + "asset": "the asset address which will be released", + "comptroller": "the comptroller address of the pool", + "destination": "the destination address of the distribution target", + "schema": "the schema of the distribution target" + } + }, + "initialize(address,uint256)": { + "details": "Initializes the deployer to owner.", + "params": { + "_accessControlManager": "The address of ACM contract", + "_loopsLimit": "Limit for the loops in the contract to avoid DOS" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pendingOwner()": { + "details": "Returns the address of the pending owner." + }, + "releaseFunds(address,address[])": { + "details": "Release funds", + "params": { + "assets": "assets to be released to distribution targets", + "comptroller": "the comptroller address of the pool" + } + }, + "removeDistributionConfig(uint8,address)": { + "details": "Remove destionation target if percentage is 0", + "params": { + "destination": "destination address of the configuration", + "schema": "schema of the configuration" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setAccessControlManager(address)": { + "custom:access": "Only Governance", + "custom:event": "Emits NewAccessControlManager event", + "details": "Admin function to set address of AccessControlManager", + "params": { + "accessControlManager_": "The new address of the AccessControlManager" + } + }, + "setPoolRegistry(address)": { + "custom:error": "ZeroAddressNotAllowed is thrown when pool registry address is zero", + "details": "Pool registry setter.", + "params": { + "_poolRegistry": "Address of the pool registry" + } + }, + "totalDistributions()": { + "details": "Returns the total number of distribution targets" + }, + "transferOwnership(address)": { + "details": "Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner." + }, + "updateAssetsState(address,address,uint8)": { + "details": "Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.", + "params": { + "asset": "Asset address.", + "comptroller": "Comptroller address (pool)", + "incomeType": "type of income" + } + } + }, + "stateVariables": { + "CORE_POOL_COMPTROLLER": { + "custom:oz-upgrades-unsafe-allow": "state-variable-immutable" + }, + "WBNB": { + "custom:oz-upgrades-unsafe-allow": "state-variable-immutable" + }, + "vBNB": { + "custom:oz-upgrades-unsafe-allow": "state-variable-immutable" + } + }, + "version": 1 + }, + "userdoc": { + "errors": { + "MaxLoopsLimitExceeded(uint256,uint256)": [ + { + "notice": "Thrown an error on maxLoopsLimit exceeds for any loop" + } + ], + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ], + "ZeroAddressNotAllowed()": [ + { + "notice": "Thrown if the supplied address is a zero address where it is not allowed" + } + ] + }, + "events": { + "AssetReleased(address,address,uint8,uint256,uint256)": { + "notice": "Event emitted when an asset is released to a target" + }, + "AssetsReservesUpdated(address,address,uint256,uint8,uint8)": { + "notice": "Event emitted after updating of the assets reserves." + }, + "DistributionConfigAdded(address,uint16,uint8)": { + "notice": "Event emitted when distribution configuration is added" + }, + "DistributionConfigRemoved(address,uint16,uint8)": { + "notice": "Event emitted when distribution configuration is removed" + }, + "DistributionConfigUpdated(address,uint16,uint16,uint8)": { + "notice": "Event emitted when distribution configuration is updated" + }, + "MaxLoopsLimitUpdated(uint256,uint256)": { + "notice": "Emitted when max loops limit is set" + }, + "NewAccessControlManager(address,address)": { + "notice": "Emitted when access control manager contract address is changed" + }, + "PoolRegistryUpdated(address,address)": { + "notice": "Emitted when pool registry address is updated" + }, + "ReservesUpdated(address,address,uint8,uint256,uint256)": { + "notice": "Event emitted when asset reserves state is updated" + } + }, + "kind": "user", + "methods": { + "CORE_POOL_COMPTROLLER()": { + "notice": "address of core pool comptroller contract" + }, + "WBNB()": { + "notice": "address of WBNB contract" + }, + "accessControlManager()": { + "notice": "Returns the address of the access control manager contract" + }, + "assetsReserves(address,address,uint8)": { + "notice": "comptroller => asset => schema => balance" + }, + "distributionTargets(uint256)": { + "notice": "configuration for different income distribution targets" + }, + "poolRegistry()": { + "notice": "address of pool registry contract" + }, + "setAccessControlManager(address)": { + "notice": "Sets the address of AccessControlManager" + }, + "totalAssetReserve(address)": { + "notice": "asset => balance" + }, + "vBNB()": { + "notice": "address of vBNB contract" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 244, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 247, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1478, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 116, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 236, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 25, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_pendingOwner", + "offset": 0, + "slot": "101", + "type": "t_address" + }, + { + "astId": 104, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 4921, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_accessControlManager", + "offset": 0, + "slot": "151", + "type": "t_contract(IAccessControlManagerV8)5106" + }, + { + "astId": 4926, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 547, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "_status", + "offset": 0, + "slot": "201", + "type": "t_uint256" + }, + { + "astId": 616, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 6066, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "maxLoopsLimit", + "offset": 0, + "slot": "251", + "type": "t_uint256" + }, + { + "astId": 6071, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 6465, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "poolRegistry", + "offset": 0, + "slot": "301", + "type": "t_address" + }, + { + "astId": 6478, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "assetsReserves", + "offset": 0, + "slot": "302", + "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_enum(Schema)6444,t_uint256)))" + }, + { + "astId": 6483, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "totalAssetReserve", + "offset": 0, + "slot": "303", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 6488, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "distributionTargets", + "offset": 0, + "slot": "304", + "type": "t_array(t_struct(DistributionConfig)6453_storage)dyn_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(DistributionConfig)6453_storage)dyn_storage": { + "base": "t_struct(DistributionConfig)6453_storage", + "encoding": "dynamic_array", + "label": "struct ProtocolShareReserve.DistributionConfig[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IAccessControlManagerV8)5106": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_enum(Schema)6444": { + "encoding": "inplace", + "label": "enum ProtocolShareReserve.Schema", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_mapping(t_address,t_mapping(t_enum(Schema)6444,t_uint256)))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => mapping(enum ProtocolShareReserve.Schema => uint256)))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_mapping(t_enum(Schema)6444,t_uint256))" + }, + "t_mapping(t_address,t_mapping(t_enum(Schema)6444,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(enum ProtocolShareReserve.Schema => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_enum(Schema)6444,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_enum(Schema)6444,t_uint256)": { + "encoding": "mapping", + "key": "t_enum(Schema)6444", + "label": "mapping(enum ProtocolShareReserve.Schema => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_struct(DistributionConfig)6453_storage": { + "encoding": "inplace", + "label": "struct ProtocolShareReserve.DistributionConfig", + "members": [ + { + "astId": 6447, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "schema", + "offset": 0, + "slot": "0", + "type": "t_enum(Schema)6444" + }, + { + "astId": 6450, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "percentage", + "offset": 1, + "slot": "0", + "type": "t_uint16" + }, + { + "astId": 6452, + "contract": "contracts/ProtocolReserve/ProtocolShareReserve.sol:ProtocolShareReserve", + "label": "destination", + "offset": 3, + "slot": "0", + "type": "t_address" + } + ], + "numberOfBytes": "32" + }, + "t_uint16": { + "encoding": "inplace", + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} diff --git a/deployments/opbnbmainnet/ProtocolShareReserve_Proxy.json b/deployments/opbnbmainnet/ProtocolShareReserve_Proxy.json new file mode 100644 index 00000000..00e1ddbd --- /dev/null +++ b/deployments/opbnbmainnet/ProtocolShareReserve_Proxy.json @@ -0,0 +1,277 @@ +{ + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "receipt": { + "to": null, + "from": "0xbD9c573ABD3ec5813cE0BF58b9aF57Fb30Bc7fB9", + "contractAddress": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "transactionIndex": 15, + "gasUsed": "842879", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000002000001000000000000040000000000000000000000020000000000000000000800000000800200000100000000000000400000000001000000000000000000000000000000000080000000000000800000000000000000000001002000000400000000001000800000000000000000000000000020000000000000000001040004000000000400000000000000000020000000000200000000000000008000000000004800000000000000000000000000", + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b", + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "logs": [ + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000da1675801de412da298dc380ca530e1bede02fd0" + ], + "data": "0x", + "logIndex": 22, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + }, + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000bd9c573abd3ec5813ce0bf58b9af57fb30bc7fb9" + ], + "data": "0x", + "logIndex": 23, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + }, + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a60deae5344f1152426ca440fb6552ea0e3005d6", + "logIndex": 24, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + }, + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014", + "logIndex": 25, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + }, + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 26, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + }, + { + "transactionIndex": 15, + "blockNumber": 17382161, + "transactionHash": "0x7effe25feac18e35569488503765855e2ede7391db342a8ec159e0ae2aa0fa07", + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f77bd1d893f67b3eb2cd256239c98ba3f238fb52", + "logIndex": 27, + "blockHash": "0x85be21e05954d72e044bdfda71c53ca34f9fc6d81d6b468d3b213468abc0bd9b" + } + ], + "blockNumber": 17382161, + "cumulativeGasUsed": "1833382", + "status": 1, + "byzantium": true + }, + "args": [ + "0xdA1675801de412da298Dc380CA530E1BeDe02fd0", + "0xF77bD1D893F67b3EB2Cd256239c98Ba3F238fb52", + "0xcd6dc687000000000000000000000000a60deae5344f1152426ca440fb6552ea0e3005d60000000000000000000000000000000000000000000000000000000000000014" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/opbnbmainnet/solcInputs/0e89febeebc7444140de8e67c9067d2c.json b/deployments/opbnbmainnet/solcInputs/0e89febeebc7444140de8e67c9067d2c.json new file mode 100644 index 00000000..557e5cb0 --- /dev/null +++ b/deployments/opbnbmainnet/solcInputs/0e89febeebc7444140de8e67c9067d2c.json @@ -0,0 +1,78 @@ +{ + "language": "Solidity", + "sources": { + "solc_0.8/openzeppelin/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 (address initialOwner) {\n _transferOwnership(initialOwner);\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" + }, + "solc_0.8/openzeppelin/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" + }, + "solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n\n constructor (address initialOwner) Ownable(initialOwner) {}\n\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n TransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n */\n function changeAdmin(address newAdmin) external virtual ifAdmin {\n _changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internall call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overriden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view virtual returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(Address.isContract(IBeacon(newBeacon).implementation()), \"ERC1967: beacon implementation is not a contract\");\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "solc_0.8/openzeppelin/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "solc_0.8/openzeppelin/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract OptimizedTransparentUpgradeableProxy is ERC1967Proxy {\n address internal immutable _ADMIN;\n\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _ADMIN = admin_;\n\n // still store it to work with EIP-1967\n bytes32 slot = _ADMIN_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(slot, admin_)\n }\n emit AdminChanged(address(0), admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n\n function _getAdmin() internal view virtual override returns (address) {\n return _ADMIN;\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate that the this implementation remains valid after an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeTo(address newImplementation) external virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n}\n" + }, + "solc_0.8/openzeppelin/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() initializer {}\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\n // contract may have been reentered.\n require(_initializing ? _isConstructor() : !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} modifier, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n function _isConstructor() private view returns (bool) {\n return !Address.isContract(address(this));\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/beacon/UpgradeableBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../../access/Ownable.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\n * implementation contract, which is where they will delegate all function calls.\n *\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\n */\ncontract UpgradeableBeacon is IBeacon, Ownable {\n address private _implementation;\n\n /**\n * @dev Emitted when the implementation returned by the beacon is changed.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\n * beacon.\n */\n\n constructor(address implementation_, address initialOwner) Ownable(initialOwner) {\n _setImplementation(implementation_);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function implementation() public view virtual override returns (address) {\n return _implementation;\n }\n\n /**\n * @dev Upgrades the beacon to a new implementation.\n *\n * Emits an {Upgraded} event.\n *\n * Requirements:\n *\n * - msg.sender must be the owner of the contract.\n * - `newImplementation` must be a contract.\n */\n function upgradeTo(address newImplementation) public virtual onlyOwner {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation contract address for this beacon\n *\n * Requirements:\n *\n * - `newImplementation` must be a contract.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"UpgradeableBeacon: implementation is not a contract\");\n _implementation = newImplementation;\n }\n}\n" + }, + "solc_0.8/openzeppelin/proxy/beacon/BeaconProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/BeaconProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../Proxy.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.\n *\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\n * conflict with the storage layout of the implementation behind the proxy.\n *\n * _Available since v3.4._\n */\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the proxy with `beacon`.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\n * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity\n * constructor.\n *\n * Requirements:\n *\n * - `beacon` must be a contract with the interface {IBeacon}.\n */\n constructor(address beacon, bytes memory data) payable {\n assert(_BEACON_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.beacon\")) - 1));\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n\n /**\n * @dev Returns the current beacon address.\n */\n function _beacon() internal view virtual returns (address) {\n return _getBeacon();\n }\n\n /**\n * @dev Returns the current implementation address of the associated beacon.\n */\n function _implementation() internal view virtual override returns (address) {\n return IBeacon(_getBeacon()).implementation();\n }\n\n /**\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\n *\n * Requirements:\n *\n * - `beacon` must be a contract.\n * - The implementation returned by `beacon` must be a contract.\n */\n function _setBeacon(address beacon, bytes memory data) internal virtual {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 999999 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/opbnbmainnet/solcInputs/6da26d3137c108aa956c278f90b592e2.json b/deployments/opbnbmainnet/solcInputs/6da26d3137c108aa956c278f90b592e2.json new file mode 100644 index 00000000..0fe7f223 --- /dev/null +++ b/deployments/opbnbmainnet/solcInputs/6da26d3137c108aa956c278f90b592e2.json @@ -0,0 +1,228 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides 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} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling 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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(account),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling 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/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1967.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967 {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../Proxy.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.\n *\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\n * conflict with the storage layout of the implementation behind the proxy.\n *\n * _Available since v3.4._\n */\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the proxy with `beacon`.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\n * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity\n * constructor.\n *\n * Requirements:\n *\n * - `beacon` must be a contract with the interface {IBeacon}.\n */\n constructor(address beacon, bytes memory data) payable {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n\n /**\n * @dev Returns the current beacon address.\n */\n function _beacon() internal view virtual returns (address) {\n return _getBeacon();\n }\n\n /**\n * @dev Returns the current implementation address of the associated beacon.\n */\n function _implementation() internal view virtual override returns (address) {\n return IBeacon(_getBeacon()).implementation();\n }\n\n /**\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\n *\n * Requirements:\n *\n * - `beacon` must be a contract.\n * - The implementation returned by `beacon` must be a contract.\n */\n function _setBeacon(address beacon, bytes memory data) internal virtual {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../../access/Ownable.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\n * implementation contract, which is where they will delegate all function calls.\n *\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\n */\ncontract UpgradeableBeacon is IBeacon, Ownable {\n address private _implementation;\n\n /**\n * @dev Emitted when the implementation returned by the beacon is changed.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\n * beacon.\n */\n constructor(address implementation_) {\n _setImplementation(implementation_);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function implementation() public view virtual override returns (address) {\n return _implementation;\n }\n\n /**\n * @dev Upgrades the beacon to a new implementation.\n *\n * Emits an {Upgraded} event.\n *\n * Requirements:\n *\n * - msg.sender must be the owner of the contract.\n * - `newImplementation` must be a contract.\n */\n function upgradeTo(address newImplementation) public virtual onlyOwner {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation contract address for this beacon\n *\n * Requirements:\n *\n * - `newImplementation` must be a contract.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"UpgradeableBeacon: implementation is not a contract\");\n _implementation = newImplementation;\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/IERC1967.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967Upgrade is IERC1967 {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\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 * 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 default value returned by this function, unless\n * it's 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(address from, address to, uint256 amount) 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 `from` to `to`.\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(address from, address to, uint256 amount) 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 // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\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 unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\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 // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\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(address owner, address spender, uint256 amount) 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(address owner, address spender, uint256 amount) 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(address from, address to, uint256 amount) 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(address from, address to, uint256 amount) 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.9.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(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\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/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlledV8\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\n /// @notice Access control manager contract\n IAccessControlManagerV8 private _accessControlManager;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when access control manager contract address is changed\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n /// @notice Thrown when the action is prohibited by AccessControlManager\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Sets the address of AccessControlManager\n * @dev Admin function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n * @custom:event Emits NewAccessControlManager event\n * @custom:access Only Governance\n */\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Returns the address of the access control manager contract\n */\n function accessControlManager() external view returns (IAccessControlManagerV8) {\n return _accessControlManager;\n }\n\n /**\n * @dev Internal function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n */\n function _setAccessControlManager(address accessControlManager_) internal {\n require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n address oldAccessControlManager = address(_accessControlManager);\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title IAccessControlManagerV8\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\n */\ninterface IAccessControlManagerV8 is IAccessControl {\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) external;\n\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface OracleInterface {\n function getPrice(address asset) external view returns (uint256);\n}\n\ninterface ResilientOracleInterface is OracleInterface {\n function updatePrice(address vToken) external;\n\n function updateAssetPrice(address asset) external;\n\n function getUnderlyingPrice(address vToken) external view returns (uint256);\n}\n\ninterface TwapInterface is OracleInterface {\n function updateTwap(address asset) external returns (uint256);\n}\n\ninterface BoundValidatorInterface {\n function validatePriceWithAnchorPrice(\n address asset,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface VBep20Interface is IERC20Metadata {\n /**\n * @notice Underlying asset for this VToken\n */\n function underlying() external view returns (address);\n}\n" + }, + "@venusprotocol/oracle/contracts/ResilientOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"./interfaces/VBep20Interface.sol\";\nimport \"./interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ResilientOracle\n * @author Venus\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\n * \n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\n * for attacking the protocol.\n * \n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\n * the protocol from oracle attacks. Currently it includes integrations with Chainlink, Pyth, Binance Oracle\n * and TWAP (Time-Weighted Average Price) oracles. TWAP uses PancakeSwap as the on-chain price source.\n * \n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per \n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot \n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source. \n * \n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\n * market. The upper bound ratio represents the deviation between reported price (the price that’s being\n * validated) and the anchor price (the price we are validating against) above which the reported price will\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\n * should be true:\n\n```\nanchorRatio = anchorPrice/reporterPrice\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\n```\n\n * In most cases, Chainlink is used as the main oracle, TWAP or Pyth oracles are used as the pivot oracle depending\n * on which supports the given market and Binance oracle is used as the fallback oracle. For some markets we may\n * use Pyth or TWAP as the main oracle if the token price is not supported by Chainlink or Binance oracles. \n * \n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\n * oracle to be stagnant and treat it like it's disabled.\n */\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\n /**\n * @dev Oracle roles:\n * **main**: The most trustworthy price source\n * **pivot**: Price oracle used as a loose sanity checker\n * **fallback**: The backup source when main oracle price is invalidated\n */\n enum OracleRole {\n MAIN,\n PIVOT,\n FALLBACK\n }\n\n struct TokenConfig {\n /// @notice asset address\n address asset;\n /// @notice `oracles` stores the oracles based on their role in the following order:\n /// [main, pivot, fallback],\n /// It can be indexed with the corresponding enum OracleRole value\n address[3] oracles;\n /// @notice `enableFlagsForOracles` stores the enabled state\n /// for each oracle in the same order as `oracles`\n bool[3] enableFlagsForOracles;\n }\n\n uint256 public constant INVALID_PRICE = 0;\n\n /// @notice Native market address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable nativeMarket;\n\n /// @notice VAI address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vai;\n\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\n /// and can serve as any underlying asset of a market that supports native tokens\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Bound validator contract address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n BoundValidatorInterface public immutable boundValidator;\n\n mapping(address => TokenConfig) private tokenConfigs;\n\n event TokenConfigAdded(\n address indexed asset,\n address indexed mainOracle,\n address indexed pivotOracle,\n address fallbackOracle\n );\n\n /// Event emitted when an oracle is set\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\n\n /// Event emitted when an oracle is enabled or disabled\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\n\n /**\n * @notice Checks whether an address is null or not\n */\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /**\n * @notice Checks whether token config exists by checking whether asset is null address\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\n * @param asset asset address\n */\n modifier checkTokenConfigExistence(address asset) {\n if (tokenConfigs[asset].asset == address(0)) revert(\"token config must exist\");\n _;\n }\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\n /// (e.g vETH on ethereum would not be supported, only vWETH)\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\n /// Set to address(0) of VAI is not existent.\n /// @param _boundValidator Address of the bound validator contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address nativeMarketAddress,\n address vaiAddress,\n BoundValidatorInterface _boundValidator\n ) notNullAddress(address(_boundValidator)) {\n nativeMarket = nativeMarketAddress;\n vai = vaiAddress;\n boundValidator = _boundValidator;\n\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract admin and sets the BoundValidator contract address\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n }\n\n /**\n * @notice Pauses oracle\n * @custom:access Only Governance\n */\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n _pause();\n }\n\n /**\n * @notice Unpauses oracle\n * @custom:access Only Governance\n */\n function unpause() external {\n _checkAccessAllowed(\"unpause()\");\n _unpause();\n }\n\n /**\n * @notice Batch sets token configs\n * @param tokenConfigs_ Token config array\n * @custom:access Only Governance\n * @custom:error Throws a length error if the length of the token configs array is 0\n */\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\n if (tokenConfigs_.length == 0) revert(\"length can't be 0\");\n uint256 numTokenConfigs = tokenConfigs_.length;\n for (uint256 i; i < numTokenConfigs; ) {\n setTokenConfig(tokenConfigs_[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Sets oracle for a given asset and role.\n * @dev Supplied asset **must** exist and main oracle may not be null\n * @param asset Asset address\n * @param oracle Oracle address\n * @param role Oracle role\n * @custom:access Only Governance\n * @custom:error Null address error if main-role oracle address is null\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\n */\n function setOracle(\n address asset,\n address oracle,\n OracleRole role\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"setOracle(address,address,uint8)\");\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\"can't set zero address to main oracle\");\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\n emit OracleSet(asset, oracle, uint256(role));\n }\n\n /**\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\n * @param asset Asset address\n * @param role Oracle role\n * @param enable Enabled boolean of the oracle\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n */\n function enableOracle(\n address asset,\n OracleRole role,\n bool enable\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"enableOracle(address,uint8,bool)\");\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\n emit OracleEnabled(asset, uint256(role), enable);\n }\n\n /**\n * @notice Updates the TWAP pivot oracle price.\n * @dev This function should always be called before calling getUnderlyingPrice\n * @param vToken vToken address\n */\n function updatePrice(address vToken) external override {\n address asset = _getUnderlyingAsset(vToken);\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @notice Updates the pivot oracle price. Currently using TWAP\n * @dev This function should always be called before calling getPrice\n * @param asset asset address\n */\n function updateAssetPrice(address asset) external {\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracle != address(0) && pivotOracleEnabled) {\n //if pivot oracle is not TwapOracle it will revert so we need to catch the revert\n try TwapInterface(pivotOracle).updateTwap(asset) {} catch {}\n }\n }\n\n /**\n * @dev Gets token config by asset address\n * @param asset asset address\n * @return tokenConfig Config for the asset\n */\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\n return tokenConfigs[asset];\n }\n\n /**\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\n * - Check if the oracle is paused globally\n * - Validate price from main oracle against pivot oracle\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\n * - Validate price from main oracle against fallback oracle if the second validation failed\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\n * main oracle price is returned.\n * @param vToken vToken address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n\n address asset = _getUnderlyingAsset(vToken);\n return _getPrice(asset);\n }\n\n /**\n * @notice Gets price of the asset\n * @param asset asset address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getPrice(address asset) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n return _getPrice(asset);\n }\n\n /**\n * @notice Sets/resets single token configs.\n * @dev main oracle **must not** be a null address\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress is thrown if asset address is null\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(\n tokenConfig.asset,\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\n );\n }\n\n /**\n * @notice Gets oracle and enabled status by asset address\n * @param asset asset address\n * @param role Oracle role\n * @return oracle Oracle address based on role\n * @return enabled Enabled flag of the oracle based on token config\n */\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\n oracle = tokenConfigs[asset].oracles[uint256(role)];\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\n }\n\n function _getPrice(address asset) internal view returns (uint256) {\n uint256 pivotPrice = INVALID_PRICE;\n\n // Get pivot oracle price, Invalid price if not available or error\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracleEnabled && pivotOracle != address(0)) {\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\n pivotPrice = pricePivot;\n } catch {}\n }\n\n // Compare main price and pivot price, return main price and if validation was successful\n // note: In case pivot oracle is not available but main price is available and\n // validation is successful, the main oracle price is returned.\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\n asset,\n pivotPrice,\n pivotOracleEnabled && pivotOracle != address(0)\n );\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\n\n // Compare fallback and pivot if main oracle comparision fails with pivot\n // Return fallback price when fallback price is validated successfully with pivot oracle\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\n\n // Lastly compare main price and fallback price\n if (\n mainPrice != INVALID_PRICE &&\n fallbackPrice != INVALID_PRICE &&\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\n ) {\n return mainPrice;\n }\n\n revert(\"invalid resilient oracle price\");\n }\n\n /**\n * @notice Gets a price for the provided asset\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\n * able to fetch a correct price\n * @param asset asset address\n * @param pivotPrice Pivot oracle price\n * @param pivotEnabled If pivot oracle is not empty and enabled\n * @return price USD price in scaled decimals\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\n * @return pivotValidated Boolean representing if the validation of main oracle price\n * and pivot oracle price were successful\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\n * address is null\n */\n function _getMainOraclePrice(\n address asset,\n uint256 pivotPrice,\n bool pivotEnabled\n ) internal view returns (uint256, bool) {\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\n if (mainOracleEnabled && mainOracle != address(0)) {\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\n if (!pivotEnabled) {\n return (mainOraclePrice, true);\n }\n if (pivotPrice == INVALID_PRICE) {\n return (mainOraclePrice, false);\n }\n return (\n mainOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\n * @param asset asset address\n * @return price USD price in 18 decimals\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\n * and pivot oracle price were successfull\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\n * address is null\n */\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\n if (fallbackEnabled && fallbackOracle != address(0)) {\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\n if (pivotPrice == INVALID_PRICE) {\n return (fallbackOraclePrice, false);\n }\n return (\n fallbackOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function returns the underlying asset of a vToken\n * @param vToken vToken address\n * @return asset underlying asset address\n */\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\n if (vToken == nativeMarket) {\n asset = NATIVE_TOKEN_ADDR;\n } else if (vToken == vai) {\n asset = vai;\n } else {\n asset = VBep20Interface(vToken).underlying();\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\nuint256 constant EXP_SCALE = 1e18;\n\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\nuint256 constant MANTISSA_ONE = EXP_SCALE;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\n" + }, + "@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title MaxLoopsLimitHelper\n * @author Venus\n * @notice Abstract contract used to avoid collection with too many items that would generate gas errors and DoS.\n */\nabstract contract MaxLoopsLimitHelper {\n // Limit for the loops to avoid the DOS\n uint256 public maxLoopsLimit;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when max loops limit is set\n event MaxLoopsLimitUpdated(uint256 oldMaxLoopsLimit, uint256 newmaxLoopsLimit);\n\n /// @notice Thrown an error on maxLoopsLimit exceeds for any loop\n error MaxLoopsLimitExceeded(uint256 loopsLimit, uint256 requiredLoops);\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function _setMaxLoopsLimit(uint256 limit) internal {\n require(limit > maxLoopsLimit, \"Comptroller: Invalid maxLoopsLimit\");\n\n uint256 oldMaxLoopsLimit = maxLoopsLimit;\n maxLoopsLimit = limit;\n\n emit MaxLoopsLimitUpdated(oldMaxLoopsLimit, limit);\n }\n\n /**\n * @notice Compare the maxLoopsLimit with number of the times loop iterate\n * @param len Length of the loops iterate\n * @custom:error MaxLoopsLimitExceeded error is thrown when loops length exceeds maxLoopsLimit\n */\n function _ensureMaxLoops(uint256 len) internal view {\n if (len > maxLoopsLimit) {\n revert MaxLoopsLimitExceeded(maxLoopsLimit, len);\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/validators.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\nerror ZeroAddressNotAllowed();\n\n/// @notice Thrown if the supplied value is 0 where it is not allowed\nerror ZeroValueNotAllowed();\n\n/// @notice Checks if the provided address is nonzero, reverts otherwise\n/// @param address_ Address to check\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\nfunction ensureNonzeroAddress(address address_) pure {\n if (address_ == address(0)) {\n revert ZeroAddressNotAllowed();\n }\n}\n\n/// @notice Checks if the provided value is nonzero, reverts otherwise\n/// @param value_ Value to check\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\nfunction ensureNonzeroValue(uint256 value_) pure {\n if (value_ == 0) {\n revert ZeroValueNotAllowed();\n }\n}\n" + }, + "contracts/Interfaces/IComptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IComptroller {\n function isComptroller() external view returns (bool);\n\n function markets(address) external view returns (bool);\n\n function getAllMarkets() external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IConverterNetwork.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAbstractTokenConverter } from \"../TokenConverter/IAbstractTokenConverter.sol\";\n\n/**\n * @title IConverterNetwork\n * @author Venus\n * @notice Interface implemented by `ConverterNetwork`.\n */\ninterface IConverterNetwork {\n /// @notice Adds new converter to the array\n /// @param _tokenConverter Address of the token converter\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Removes converter from the array\n /// @param _tokenConverter Address of the token converter\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external;\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance);\n\n /// @notice This function returns the array containing all the converters addresses\n /// @return Array containing all the converters addresses\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory);\n\n /// @notice This function checks for given address is converter or not\n /// @param _tokenConverter Address of the token converter\n /// @return boolean true if given address is converter otherwise false\n function isTokenConverter(address _tokenConverter) external view returns (bool);\n}\n" + }, + "contracts/Interfaces/IIncomeDestination.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IIncomeDestination {\n function updateAssetsState(address comptroller, address asset) external;\n}\n" + }, + "contracts/Interfaces/IPoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IPoolRegistry {\n /// @notice Get VToken in the Pool for an Asset\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\n\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION\n }\n\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) external;\n}\n" + }, + "contracts/Interfaces/IRiskFund.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IRiskFund\n * @author Venus\n * @notice Interface implemented by `RiskFund`.\n */\ninterface IRiskFund {\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updatePoolState(\n address comptroller,\n address asset,\n uint256 amount\n ) external;\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n\n/**\n * @title IRiskFundGetters\n * @author Venus\n * @notice Interface implemented by `RiskFund` for getter methods.\n */\ninterface IRiskFundGetters {\n function convertibleBaseAsset() external view returns (address);\n}\n" + }, + "contracts/Interfaces/IRiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IRiskFundConverter {\n function updateAssetsState(address comptroller, address asset) external;\n\n function getPools(address asset) external view returns (address[] memory);\n}\n" + }, + "contracts/Interfaces/IShortfall.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IShortfall\n * @author Venus\n * @notice Interface implemented by `Shortfall`.\n */\ninterface IShortfall {\n function convertibleBaseAsset() external returns (address);\n}\n" + }, + "contracts/Interfaces/IVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IVToken {\n function underlying() external view returns (address);\n}\n" + }, + "contracts/Interfaces/IXVSVault.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @title IXVSVaultProxy\n/// @author Venus\n/// @notice Interface implemented by `XVSVault`.\ninterface IXVSVault {\n function xvsStore() external view returns (address);\n}\n" + }, + "contracts/ProtocolReserve/ProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IProtocolShareReserve } from \"../Interfaces/IProtocolShareReserve.sol\";\nimport { IComptroller } from \"../Interfaces/IComptroller.sol\";\nimport { IPoolRegistry } from \"../Interfaces/IPoolRegistry.sol\";\nimport { IVToken } from \"../Interfaces/IVToken.sol\";\nimport { IIncomeDestination } from \"../Interfaces/IIncomeDestination.sol\";\n\nerror InvalidAddress();\nerror UnsupportedAsset();\nerror InvalidTotalPercentage();\nerror InvalidMaxLoopsLimit();\n\ncontract ProtocolShareReserve is\n AccessControlledV8,\n ReentrancyGuardUpgradeable,\n MaxLoopsLimitHelper,\n IProtocolShareReserve\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice protocol income is categorized into two schemas.\n /// The first schema is for spread income\n /// The second schema is for liquidation income\n enum Schema {\n PROTOCOL_RESERVES,\n ADDITIONAL_REVENUE\n }\n\n struct DistributionConfig {\n Schema schema;\n /// @dev percenatge is represented without any scale\n uint16 percentage;\n address destination;\n }\n\n /// @notice address of core pool comptroller contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n /// @notice address of WBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable WBNB;\n\n /// @notice address of vBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vBNB;\n\n /// @notice address of pool registry contract\n address public poolRegistry;\n\n uint16 public constant MAX_PERCENT = 1e4;\n\n /// @notice comptroller => asset => schema => balance\n mapping(address => mapping(address => mapping(Schema => uint256))) public assetsReserves;\n\n /// @notice asset => balance\n mapping(address => uint256) public totalAssetReserve;\n\n /// @notice configuration for different income distribution targets\n DistributionConfig[] public distributionTargets;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Event emitted after updating of the assets reserves.\n event AssetsReservesUpdated(\n address indexed comptroller,\n address indexed asset,\n uint256 amount,\n IncomeType incomeType,\n Schema schema\n );\n\n /// @notice Event emitted when an asset is released to a target\n event AssetReleased(\n address indexed destination,\n address indexed asset,\n Schema schema,\n uint256 percent,\n uint256 amount\n );\n\n /// @notice Event emitted when asset reserves state is updated\n event ReservesUpdated(\n address indexed comptroller,\n address indexed asset,\n Schema schema,\n uint256 oldBalance,\n uint256 newBalance\n );\n\n /// @notice Event emitted when distribution configuration is updated\n event DistributionConfigUpdated(\n address indexed destination,\n uint16 oldPercentage,\n uint16 newPercentage,\n Schema schema\n );\n\n /// @notice Event emitted when distribution configuration is added\n event DistributionConfigAdded(address indexed destination, uint16 percentage, Schema schema);\n\n /// @notice Event emitted when distribution configuration is removed\n event DistributionConfigRemoved(address indexed destination, uint16 percentage, Schema schema);\n\n /**\n * @dev Constructor to initialize the immutable variables\n * @param _corePoolComptroller The address of core pool comptroller\n * @param _wbnb The address of WBNB\n * @param _vbnb The address of vBNB\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _corePoolComptroller,\n address _wbnb,\n address _vbnb\n ) {\n ensureNonzeroAddress(_corePoolComptroller);\n ensureNonzeroAddress(_wbnb);\n ensureNonzeroAddress(_vbnb);\n\n CORE_POOL_COMPTROLLER = _corePoolComptroller;\n WBNB = _wbnb;\n vBNB = _vbnb;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @dev Initializes the deployer to owner.\n * @param _accessControlManager The address of ACM contract\n * @param _loopsLimit Limit for the loops in the contract to avoid DOS\n */\n function initialize(address _accessControlManager, uint256 _loopsLimit) external initializer {\n __AccessControlled_init(_accessControlManager);\n __ReentrancyGuard_init();\n _setMaxLoopsLimit(_loopsLimit);\n }\n\n /**\n * @dev Pool registry setter.\n * @param _poolRegistry Address of the pool registry\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n */\n function setPoolRegistry(address _poolRegistry) external onlyOwner {\n ensureNonzeroAddress(_poolRegistry);\n emit PoolRegistryUpdated(poolRegistry, _poolRegistry);\n poolRegistry = _poolRegistry;\n }\n\n /**\n * @dev Add or update destination targets based on destination address\n * @param configs configurations of the destinations.\n */\n function addOrUpdateDistributionConfigs(DistributionConfig[] calldata configs) external nonReentrant {\n _checkAccessAllowed(\"addOrUpdateDistributionConfigs(DistributionConfig[])\");\n\n for (uint256 i = 0; i < configs.length; ) {\n DistributionConfig memory _config = configs[i];\n ensureNonzeroAddress(_config.destination);\n\n bool updated = false;\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 j = 0; j < distributionTargetsLength; ) {\n DistributionConfig storage config = distributionTargets[j];\n\n if (_config.schema == config.schema && config.destination == _config.destination) {\n emit DistributionConfigUpdated(\n _config.destination,\n config.percentage,\n _config.percentage,\n _config.schema\n );\n config.percentage = _config.percentage;\n updated = true;\n break;\n }\n\n unchecked {\n ++j;\n }\n }\n\n if (!updated) {\n distributionTargets.push(_config);\n emit DistributionConfigAdded(_config.destination, _config.percentage, _config.schema);\n }\n\n unchecked {\n ++i;\n }\n }\n\n _ensurePercentages();\n _ensureMaxLoops(distributionTargets.length);\n }\n\n /**\n * @dev Remove destionation target if percentage is 0\n * @param schema schema of the configuration\n * @param destination destination address of the configuration\n */\n function removeDistributionConfig(Schema schema, address destination) external {\n _checkAccessAllowed(\"removeDistributionConfig(Schema,address)\");\n\n uint256 distributionIndex;\n bool found = false;\n for (uint256 i = 0; i < distributionTargets.length; ) {\n DistributionConfig storage config = distributionTargets[i];\n\n if (schema == config.schema && destination == config.destination && config.percentage == 0) {\n found = true;\n distributionIndex = i;\n break;\n }\n\n unchecked {\n ++i;\n }\n }\n\n if (found) {\n emit DistributionConfigRemoved(\n distributionTargets[distributionIndex].destination,\n distributionTargets[distributionIndex].percentage,\n distributionTargets[distributionIndex].schema\n );\n\n distributionTargets[distributionIndex] = distributionTargets[distributionTargets.length - 1];\n distributionTargets.pop();\n }\n\n _ensurePercentages();\n }\n\n /**\n * @dev Release funds\n * @param comptroller the comptroller address of the pool\n * @param assets assets to be released to distribution targets\n */\n function releaseFunds(address comptroller, address[] calldata assets) external nonReentrant {\n for (uint256 i = 0; i < assets.length; ) {\n _releaseFund(comptroller, assets[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Used to find out the amount of funds that's going to be released when release funds is called.\n * @param comptroller the comptroller address of the pool\n * @param schema the schema of the distribution target\n * @param destination the destination address of the distribution target\n * @param asset the asset address which will be released\n */\n function getUnreleasedFunds(\n address comptroller,\n Schema schema,\n address destination,\n address asset\n ) external view returns (uint256) {\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\n DistributionConfig storage _config = distributionTargets[i];\n if (_config.schema == schema && _config.destination == destination) {\n uint256 total = assetsReserves[comptroller][asset][schema];\n return (total * _config.percentage) / MAX_PERCENT;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Returns the total number of distribution targets\n */\n function totalDistributions() external view returns (uint256) {\n return distributionTargets.length;\n }\n\n /**\n * @dev Used to find out the percentage distribution for a particular destination based on schema\n * @param destination the destination address of the distribution target\n * @param schema the schema of the distribution target\n * @return percentage percentage distribution\n */\n function getPercentageDistribution(address destination, Schema schema) external view returns (uint256) {\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\n DistributionConfig memory config = distributionTargets[i];\n\n if (config.destination == destination && config.schema == schema) {\n return config.percentage;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\n * @param comptroller Comptroller address (pool)\n * @param asset Asset address.\n * @param incomeType type of income\n */\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) public override(IProtocolShareReserve) nonReentrant {\n if (!IComptroller(comptroller).isComptroller()) revert InvalidAddress();\n ensureNonzeroAddress(asset);\n\n if (\n comptroller != CORE_POOL_COMPTROLLER &&\n IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) == address(0)\n ) revert InvalidAddress();\n\n Schema schema = _getSchema(incomeType);\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\n uint256 assetReserve = totalAssetReserve[asset];\n\n if (currentBalance > assetReserve) {\n uint256 balanceDifference;\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n\n assetsReserves[comptroller][asset][schema] += balanceDifference;\n totalAssetReserve[asset] += balanceDifference;\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference, incomeType, schema);\n }\n }\n\n /**\n * @dev asset from a particular pool to be release to distribution targets\n * @param comptroller Comptroller address(pool)\n * @param asset Asset address.\n */\n function _releaseFund(address comptroller, address asset) internal {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint256[] memory schemaBalances = new uint256[](totalSchemas);\n uint256 totalBalance;\n for (uint256 schemaValue; schemaValue < totalSchemas; ) {\n schemaBalances[schemaValue] = assetsReserves[comptroller][asset][Schema(schemaValue)];\n totalBalance += schemaBalances[schemaValue];\n\n unchecked {\n ++schemaValue;\n }\n }\n\n if (totalBalance == 0) {\n return;\n }\n\n uint256[] memory totalTransferAmounts = new uint256[](totalSchemas);\n for (uint256 i = 0; i < distributionTargets.length; ) {\n DistributionConfig memory _config = distributionTargets[i];\n\n uint256 transferAmount = (schemaBalances[uint256(_config.schema)] * _config.percentage) / MAX_PERCENT;\n totalTransferAmounts[uint256(_config.schema)] += transferAmount;\n\n if (transferAmount != 0) {\n IERC20Upgradeable(asset).safeTransfer(_config.destination, transferAmount);\n IIncomeDestination(_config.destination).updateAssetsState(comptroller, asset);\n\n emit AssetReleased(_config.destination, asset, _config.schema, _config.percentage, transferAmount);\n }\n\n unchecked {\n ++i;\n }\n }\n\n uint256[] memory newSchemaBalances = new uint256[](totalSchemas);\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\n newSchemaBalances[schemaValue] = schemaBalances[schemaValue] - totalTransferAmounts[schemaValue];\n assetsReserves[comptroller][asset][Schema(schemaValue)] = newSchemaBalances[schemaValue];\n totalAssetReserve[asset] = totalAssetReserve[asset] - totalTransferAmounts[schemaValue];\n\n emit ReservesUpdated(\n comptroller,\n asset,\n Schema(schemaValue),\n schemaBalances[schemaValue],\n newSchemaBalances[schemaValue]\n );\n\n unchecked {\n ++schemaValue;\n }\n }\n }\n\n /**\n * @dev Returns the schema based on income type\n * @param incomeType type of income\n * @return schema schema for distribution\n */\n function _getSchema(IncomeType incomeType) internal view returns (Schema schema) {\n schema = Schema.ADDITIONAL_REVENUE;\n\n if (incomeType == IncomeType.SPREAD) {\n schema = Schema.PROTOCOL_RESERVES;\n }\n }\n\n /**\n * @dev This ensures that the total percentage of all the distribution targets is 100% or 0%\n */\n function _ensurePercentages() internal view {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint16[] memory totalPercentages = new uint16[](totalSchemas);\n\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\n DistributionConfig memory config = distributionTargets[i];\n totalPercentages[uint256(config.schema)] += config.percentage;\n\n unchecked {\n ++i;\n }\n }\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\n if (totalPercentages[schemaValue] != MAX_PERCENT && totalPercentages[schemaValue] != 0)\n revert InvalidTotalPercentage();\n\n unchecked {\n ++schemaValue;\n }\n }\n }\n\n /**\n * @dev Returns the underlying asset address for the vToken\n * @param vToken vToken address\n * @return asset address of asset\n */\n function _getUnderlying(address vToken) internal view returns (address) {\n if (vToken == vBNB) {\n return WBNB;\n } else {\n return IVToken(vToken).underlying();\n }\n }\n}\n" + }, + "contracts/ProtocolReserve/RiskFundStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\n\n/// @title ReserveHelpersStorage\n/// @author Venus\n/// @dev Reserve helpers storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract ReserveHelpersStorage is Ownable2StepUpgradeable {\n /// @notice Deprecated slot for assetReserves mapping\n bytes32 private __deprecatedSlot1;\n\n /// @notice Available asset's fund per pool in RiskFund\n /// Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) public poolAssetsFunds;\n\n /// @notice Deprecated slot for poolRegistry address\n bytes32 private __deprecatedSlot2;\n /// @notice Deprecated slot for status variable\n bytes32 private __deprecatedSlot3;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n uint256[46] private __gap;\n}\n\n/// @title MaxLoopsLimitHelpersStorage\n/// @author Venus\n/// @dev Max loop limit helpers storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract MaxLoopsLimitHelpersStorage {\n /// @notice Limit for the loops to avoid the DOS\n /// @notice This state is deprecated, using it to prevent storage collision\n uint256 public maxLoopsLimit;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n uint256[49] private __gap;\n}\n\n/// @title RiskFundV1Storage\n/// @author Venus\n/// @dev Risk fund V1 storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundV1Storage is ReserveHelpersStorage, MaxLoopsLimitHelpersStorage {\n /// @notice Address of base asset\n address public convertibleBaseAsset;\n /// @notice Address of shortfall contract\n address public shortfall;\n\n /// @notice This state is deprecated, using it to prevent storage collision\n address private pancakeSwapRouter;\n /// @notice This state is deprecated, using it to prevent storage collision\n uint256 private minAmountToConvert;\n}\n\n/// @title RiskFundV2Storage\n/// @author Venus\n/// @dev Risk fund V2 storage\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeable {\n /// @notice Risk fund converter address\n address public riskFundConverter;\n}\n" + }, + "contracts/ProtocolReserve/RiskFundV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IRiskFund } from \"../Interfaces/IRiskFund.sol\";\nimport { IRiskFundConverter } from \"../Interfaces/IRiskFundConverter.sol\";\nimport { RiskFundV2Storage } from \"./RiskFundStorage.sol\";\n\n/// @title RiskFundV2\n/// @author Venus\n/// @notice Contract with basic features to hold base asset for different Comptrollers\n/// @dev This contract does not support BNB\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Emitted when convertible base asset address is updated\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\n\n /// @notice Emitted when risk fund converter address is updated\n event RiskFundConverterUpdated(address indexed oldRiskFundConverter, address indexed newRiskFundConverter);\n\n /// @notice Emitted when shortfall contract address is updated\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\n\n /// @notice Emitted when reserves are transferred for auction\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\n\n /// @notice Emitted when pool asset states is updated with amount transferred to this contract\n event PoolAssetsIncreased(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\n event PoolAssetsDecreased(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Event emitted when tokens are swept\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /// @notice Event emitted when tokens are swept and transferred from pool\n event SweepTokenFromPool(address indexed token, address indexed comptroller, uint256 amount);\n\n /// @notice Error is thrown when updatePoolState is not called by riskFundConverter\n error InvalidRiskFundConverter();\n\n /// @notice Error is thrown when transferReserveForAuction is called by non shortfall address\n error InvalidShortfallAddress();\n\n /// @notice thrown when amount entered is greater than balance\n error InsufficientBalance();\n\n /// @notice Error is thrown when pool reserve is less than the amount needed\n error InsufficientPoolReserve(address comptroller, uint256 amount, uint256 poolReserve);\n\n /// @dev Convertible base asset setter\n /// @param convertibleBaseAsset_ Address of the convertible base asset\n /// @custom:event ConvertibleBaseAssetUpdated emit on success\n /// @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n /// @custom:access Only Governance\n function setConvertibleBaseAsset(address convertibleBaseAsset_) external onlyOwner {\n ensureNonzeroAddress(convertibleBaseAsset_);\n emit ConvertibleBaseAssetUpdated(convertibleBaseAsset, convertibleBaseAsset_);\n convertibleBaseAsset = convertibleBaseAsset_;\n }\n\n /// @dev Risk fund converter setter\n /// @param riskFundConverter_ Address of the risk fund converter\n /// @custom:event RiskFundConverterUpdated emit on success\n /// @custom:error ZeroAddressNotAllowed is thrown when risk fund converter address is zero\n /// @custom:access Only Governance\n function setRiskFundConverter(address riskFundConverter_) external onlyOwner {\n ensureNonzeroAddress(riskFundConverter_);\n emit RiskFundConverterUpdated(riskFundConverter, riskFundConverter_);\n riskFundConverter = riskFundConverter_;\n }\n\n /// @dev Shortfall contract address setter\n /// @param shortfallContractAddress_ Address of the auction contract\n /// @custom:event ShortfallContractUpdated emit on success\n /// @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n /// @custom:access Only Governance\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\n ensureNonzeroAddress(shortfallContractAddress_);\n emit ShortfallContractUpdated(shortfall, shortfallContractAddress_);\n shortfall = shortfallContractAddress_;\n }\n\n /// @dev Transfer tokens for auction to shortfall contract\n /// @param comptroller Comptroller of the pool\n /// @param amount Amount to be transferred to the shortfall\n /// @return Amount of tokens transferred to the shortfall\n /// @custom:event TransferredReserveForAuction emit on success\n /// @custom:error InvalidShortfallAddress is thrown when caller is not shortfall contract\n /// @custom:error InsufficientPoolReserve is thrown when pool reserve is less than the amount needed\n /// @custom:access Only Shortfall contract\n function transferReserveForAuction(address comptroller, uint256 amount)\n external\n override\n nonReentrant\n returns (uint256)\n {\n uint256 poolReserve = poolAssetsFunds[comptroller][convertibleBaseAsset];\n\n if (msg.sender != shortfall) {\n revert InvalidShortfallAddress();\n }\n if (amount > poolReserve) {\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\n }\n\n unchecked {\n poolAssetsFunds[comptroller][convertibleBaseAsset] = poolReserve - amount;\n }\n\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall, amount);\n emit TransferredReserveForAuction(comptroller, amount);\n\n return amount;\n }\n\n /// @notice Function to sweep baseAsset for pool, Tokens are sent to address(to)\n /// @param tokenAddress Address of the asset(token)\n /// @param to Address to which assets will be transferred\n /// @param amount Amount need to sweep for the pool\n /// @custom:event Emits SweepToken event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\n /// @custom:access Only Governance\n function sweepToken(\n address tokenAddress,\n address to,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(to);\n ensureNonzeroValue(amount);\n\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n preSweepToken(tokenAddress, amount);\n token.safeTransfer(to, amount);\n\n emit SweepToken(tokenAddress, to, amount);\n }\n\n /// @notice Function to sweep token from pool\n /// @param tokenAddress Address of the asset(token)\n /// @param comptroller Pool address to which assets will be transferred\n /// @param amount Amount need to sweep from the pool\n /// @custom:event Emits sweepTokenFromPool event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zero\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\n /// @custom:access Only Governance\n function sweepTokenFromPool(\n address tokenAddress,\n address comptroller,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(comptroller);\n ensureNonzeroValue(amount);\n\n uint256 poolReserve = poolAssetsFunds[comptroller][tokenAddress];\n\n if (amount > poolReserve) {\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\n }\n\n unchecked {\n poolAssetsFunds[comptroller][tokenAddress] = poolReserve - amount;\n }\n\n IERC20Upgradeable(tokenAddress).safeTransfer(comptroller, amount);\n\n emit SweepTokenFromPool(tokenAddress, comptroller, amount);\n }\n\n /**\n * @notice Get the Amount of the Base asset in the risk fund for the specific pool.\n * @param comptroller Comptroller address(pool).\n * @return Base Asset's reserve in risk fund.\n */\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256) {\n return poolAssetsFunds[comptroller][convertibleBaseAsset];\n }\n\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\n /// @param comptroller Comptroller address (pool)\n /// @param asset Address of the asset(token)\n /// @param amount Amount transferred for the pool\n /// @custom:event PoolAssetsIncreased emits on success\n /// @custom:error InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\n /// @custom:access Only RiskFundConverter contract\n function updatePoolState(\n address comptroller,\n address asset,\n uint256 amount\n ) public {\n if (msg.sender != riskFundConverter) {\n revert InvalidRiskFundConverter();\n }\n\n poolAssetsFunds[comptroller][asset] += amount;\n emit PoolAssetsIncreased(comptroller, asset, amount);\n }\n\n /// @dev Operations to perform before sweeping tokens\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\n function preSweepToken(address tokenAddress, uint256 amount) internal {\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\n if (amount > balance) revert InsufficientBalance();\n\n address[] memory pools = IRiskFundConverter(riskFundConverter).getPools(tokenAddress);\n\n uint256 assetReserves;\n uint256 poolsLength = pools.length;\n for (uint256 i; i < poolsLength; ) {\n assetReserves += poolAssetsFunds[pools[i]][tokenAddress];\n unchecked {\n ++i;\n }\n }\n\n uint256 balanceDiff = balance - assetReserves;\n\n if (balanceDiff < amount) {\n uint256 amountDiff;\n unchecked {\n amountDiff = amount - balanceDiff;\n }\n uint256 distributedShare;\n for (uint256 i; i < poolsLength; ) {\n if (poolAssetsFunds[pools[i]][tokenAddress] != 0) {\n uint256 poolAmountShare;\n if (i < (poolsLength - 1)) {\n poolAmountShare = (poolAssetsFunds[pools[i]][tokenAddress] * amount) / assetReserves;\n distributedShare += poolAmountShare;\n } else {\n poolAmountShare = amountDiff - distributedShare;\n }\n poolAssetsFunds[pools[i]][tokenAddress] -= poolAmountShare;\n emit PoolAssetsDecreased(pools[i], tokenAddress, poolAmountShare);\n }\n unchecked {\n ++i;\n }\n }\n }\n }\n}\n" + }, + "contracts/ProtocolReserve/XVSVaultTreasury.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IXVSVault } from \"../Interfaces/IXVSVault.sol\";\n\n/// @title XVSVaultTreasury\n/// @author Venus\n/// @notice XVSVaultTreasury stores the tokens sent by SingleTokenConverter(XVS) and funds XVSVault\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract XVSVaultTreasury is AccessControlledV8, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The xvs token address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable XVS_ADDRESS;\n\n /// @notice The xvsvault address\n address public xvsVault;\n\n /// @notice Emitted when XVS vault address is updated\n event XVSVaultUpdated(address indexed oldXVSVault, address indexed newXVSVault);\n\n /// @notice Emitted when funds transferred to XVSStore address\n event FundsTransferredToXVSStore(address indexed xvsStore, uint256 amountMantissa);\n\n /// @notice Thrown when given input amount is zero\n error InsufficientBalance();\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @param xvsAddress_ XVS token address\n constructor(address xvsAddress_) {\n ensureNonzeroAddress(xvsAddress_);\n XVS_ADDRESS = xvsAddress_;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param xvsVault_ XVSVault address\n /// @custom:event XVSVaultUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when XVS vault address is zero\n function initialize(address accessControlManager_, address xvsVault_) public initializer {\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n _setXVSVault(xvsVault_);\n }\n\n /// @dev XVS vault setter\n /// @param xvsVault_ Address of the XVS vault\n /// @custom:event XVSVaultUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when XVS vault address is zero\n function setXVSVault(address xvsVault_) external onlyOwner {\n _setXVSVault(xvsVault_);\n }\n\n /// @notice This function transfers funds to the XVS vault\n /// @param amountMantissa Amount to be sent to XVS vault\n /// @custom:event FundsTransferredToXVSStore emits on success\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\n /// @custom:access Restricted by ACM\n function fundXVSVault(uint256 amountMantissa) external nonReentrant {\n _checkAccessAllowed(\"fundXVSVault(uint256)\");\n ensureNonzeroValue(amountMantissa);\n\n uint256 balance = IERC20Upgradeable(XVS_ADDRESS).balanceOf(address(this));\n\n if (balance < amountMantissa) {\n revert InsufficientBalance();\n }\n\n address xvsStore = IXVSVault(xvsVault).xvsStore();\n ensureNonzeroAddress(xvsStore);\n IERC20Upgradeable(XVS_ADDRESS).safeTransfer(xvsStore, amountMantissa);\n\n emit FundsTransferredToXVSStore(xvsStore, amountMantissa);\n }\n\n /// @dev XVS vault setter\n /// @param xvsVault_ Address of the XVS vault\n /// @custom:event XVSVaultUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when XVS vault address is zero\n function _setXVSVault(address xvsVault_) internal {\n ensureNonzeroAddress(xvsVault_);\n emit XVSVaultUpdated(xvsVault, xvsVault_);\n xvsVault = xvsVault_;\n }\n}\n" + }, + "contracts/Test/imports.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n// This file is needed to make hardhat and typechain generate artifacts for\n// contracts we depend on (e.g. in tests or deployments) but not use directly.\n// Another way to do this would be to use hardhat-dependency-compiler, but\n// since we only have a couple of dependencies, installing a separate package\n// seems an overhead.\n\nimport { UpgradeableBeacon } from \"@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol\";\nimport { BeaconProxy } from \"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\";\n" + }, + "contracts/Test/Mocks/MockACM.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { AccessControl } from \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract MockACM is AccessControl {\n /// @notice Emitted when an account is given a permission to a certain contract function\n /// @dev If contract address is 0x000..0 this means that the account is a default admin of this function and\n /// can call any contract function with this signature\n event PermissionGranted(address account, address contractAddress, string functionSig);\n\n /// @notice Emitted when an account is revoked a permission to a certain contract function\n event PermissionRevoked(address account, address contractAddress, string functionSig);\n\n constructor() {\n // Grant the contract deployer the default admin role: it will be able\n // to grant and revoke any roles\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Gives a function call permission to one single account\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n * @param contractAddress address of contract for which call permissions will be granted\n * @dev if contractAddress is zero address, the account can access the specified function\n * on **any** contract managed by this ACL\n * @param functionSig signature e.g. \"functionName(uint256,bool)\"\n * @param accountToPermit account that will be given access to the contract function\n * @custom:event Emits a {RoleGranted} and {PermissionGranted} events.\n */\n function giveCallPermission(\n address contractAddress,\n string memory functionSig,\n address accountToPermit\n ) public {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n grantRole(role, accountToPermit);\n emit PermissionGranted(accountToPermit, contractAddress, functionSig);\n }\n\n /**\n * @notice Revokes an account's permission to a particular function call\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n * \t\tMay emit a {RoleRevoked} event.\n * @param contractAddress address of contract for which call permissions will be revoked\n * @param functionSig signature e.g. \"functionName(uint256,bool)\"\n * @custom:event Emits {RoleRevoked} and {PermissionRevoked} events.\n */\n function revokeCallPermission(\n address contractAddress,\n string memory functionSig,\n address accountToRevoke\n ) public {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n revokeRole(role, accountToRevoke);\n emit PermissionRevoked(accountToRevoke, contractAddress, functionSig);\n }\n\n /**\n * @notice Verifies if the given account can call a contract's guarded function\n * @dev Since restricted contracts using this function as a permission hook, we can get contracts address with msg.sender\n * @param account for which call permissions will be checked\n * @param functionSig restricted function signature e.g. \"functionName(uint256,bool)\"\n * @return false if the user account cannot call the particular contract function\n *\n */\n function isAllowedToCall(address account, string memory functionSig) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(msg.sender, functionSig));\n\n if (hasRole(role, account)) {\n return true;\n } else {\n role = keccak256(abi.encodePacked(address(0), functionSig));\n return hasRole(role, account);\n }\n }\n\n /**\n * @notice Verifies if the given account can call a contract's guarded function\n * @dev This function is used as a view function to check permissions rather than contract hook for access restriction check.\n * @param account for which call permissions will be checked against\n * @param contractAddress address of the restricted contract\n * @param functionSig signature of the restricted function e.g. \"functionName(uint256,bool)\"\n * @return false if the user account cannot call the particular contract function\n */\n function hasPermission(\n address account,\n address contractAddress,\n string memory functionSig\n ) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n return hasRole(role, account);\n }\n}\n" + }, + "contracts/Test/Mocks/MockArraySorter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\nimport { sort } from \"../../Utils/ArrayHelpers.sol\";\n\ncontract MockArraySorter {\n function sortArray(uint256[] memory balances, address[] memory addrs)\n external\n view\n returns (address[] memory, uint256[] memory)\n {\n sort(balances, addrs);\n return (addrs, balances);\n }\n}\n" + }, + "contracts/Test/Mocks/MockConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\n\nimport { AbstractTokenConverter } from \"../../TokenConverter/AbstractTokenConverter.sol\";\nimport { IRiskFundGetters } from \"../../Interfaces/IRiskFund.sol\";\n\ncontract MockConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) public assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) public poolsAssetsReserves;\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n function mockPrivateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 balanceDiff\n ) external {\n _privateConversion(comptroller, tokenAddressOut, balanceDiff);\n }\n\n function AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) public initializer {\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n assetsReserves[tokenAddressIn] += convertedTokenInBalance;\n poolsAssetsReserves[comptroller][tokenAddressIn] += convertedTokenInBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @notice Get base asset address\n function _getDestinationBaseAsset() internal view override returns (address) {\n return IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/Test/Mocks/MockDeflationaryToken.sol": { + "content": "pragma solidity 0.8.13;\n\ncontract MockDeflatingToken {\n string public constant NAME = \"Deflating Test Token\";\n string public constant SYMBOL = \"DTT\";\n uint8 public constant DECIMALS = 18;\n uint256 public totalSupply;\n mapping(address => uint256) public balanceOf;\n mapping(address => mapping(address => uint256)) public allowance;\n\n bytes32 public immutable DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n event Approval(address indexed owner, address indexed spender, uint256 value);\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n constructor(uint256 _totalSupply) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string NAME,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(NAME)),\n keccak256(bytes(\"1\")),\n chainId,\n address(this)\n )\n );\n _mint(msg.sender, _totalSupply);\n }\n\n function approve(address spender, uint256 value) external returns (bool) {\n _approve(msg.sender, spender, value);\n return true;\n }\n\n function transfer(address to, uint256 value) external returns (bool) {\n _transfer(msg.sender, to, value);\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n ) external returns (bool) {\n if (allowance[from][msg.sender] != type(uint256).max) {\n allowance[from][msg.sender] = allowance[from][msg.sender] - value;\n }\n _transfer(from, to, value);\n return true;\n }\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"EXPIRED\");\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNATURE\");\n _approve(owner, spender, value);\n }\n\n function _mint(address to, uint256 value) internal {\n totalSupply = totalSupply + value;\n balanceOf[to] = balanceOf[to] + value;\n emit Transfer(address(0), to, value);\n }\n\n function _burn(address from, uint256 value) internal {\n balanceOf[from] = balanceOf[from] - value;\n totalSupply = totalSupply - value;\n emit Transfer(from, address(0), value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n ) private {\n allowance[owner][spender] = value;\n emit Approval(owner, spender, value);\n }\n\n function _transfer(\n address from,\n address to,\n uint256 value\n ) private {\n uint256 burnAmount = value / 100;\n _burn(from, burnAmount);\n uint256 transferAmount = value - burnAmount;\n balanceOf[from] = balanceOf[from] - transferAmount;\n balanceOf[to] = balanceOf[to] + transferAmount;\n emit Transfer(from, to, transferAmount);\n }\n}\n" + }, + "contracts/Test/Mocks/MockRiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { RiskFundConverter } from \"../../TokenConverter/RiskFundConverter.sol\";\n\ncontract MockRiskFundConverter is RiskFundConverter {\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) RiskFundConverter(corePoolComptroller_, vBNB_, nativeWrapped_) {}\n\n function postConversionHookMock(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) external {\n super._postConversionHook(tokenInAddress, tokenOutAddress, amountIn, amountOut);\n }\n\n function preTransferHookMock(address tokenOutAddress, uint256 amountOut) external {\n super._preTransferHook(tokenOutAddress, amountOut);\n }\n\n function setAssetsReserves(address asset, uint256 amount) external {\n assetsReserves[asset] = amount;\n }\n\n function setPoolsAssetsReserves(\n address comptroller,\n address asset,\n uint256 amount\n ) external {\n poolsAssetsReserves[comptroller][asset] = amount;\n }\n\n function getPoolsAssetsReserves(address comptroller, address asset) external view returns (uint256) {\n return poolsAssetsReserves[comptroller][asset];\n }\n\n function getAssetsReserves(address asset) external view returns (uint256) {\n return assetsReserves[asset];\n }\n}\n" + }, + "contracts/Test/Mocks/MockToken.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 { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockToken is ERC20 {\n uint8 private immutable _decimals;\n\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) ERC20(name_, symbol_) {\n _decimals = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function allocateTo(address owner, uint256 amount) external {\n _mint(owner, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/TokenConverter/AbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { MANTISSA_ONE, EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\nimport { IAbstractTokenConverter } from \"./IAbstractTokenConverter.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @title AbstractTokenConverter\n/// @author Venus\n/// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter\n/*\n * This contract specifies four functions for converting tokens, each applicable under following circumstances:\n *\n * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token\n * In this scenario, functions supporting fees can only be utilized to convert tokens which are:\n * a. convertExactTokensSupportingFeeOnTransferTokens\n * b. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions supporting fee can only be utilized to convert tokens which are:\n * similar to Case I.\n *\n * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * a. convertExactTokens\n * b. convertForExactTokens\n * c. convertExactTokensSupportingFeeOnTransferTokens\n * d. convertForExactTokensSupportingFeeOnTransferTokens\n *\n * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token\n * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:\n * similar to Case III.\n *\n * ------------------------------------------------------------------------------------------------------------------------------------\n * Example 1:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInAmount - 100\n * tokenOutMinAmount - minimum amount desired by the user(let's say 70)\n * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).\n * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount\n * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred\n * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say\n * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will\n * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`\n * function for tokenIn as deflationary token.\n *\n * Example 2:-\n * tokenInAddress - 0xaaaa.....\n * tokenOutAddress - 0xbbbb.....\n * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)\n * tokenOutAmount - 70\n * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary\n * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),\n * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer\n * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be\n * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then\n * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the\n * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was\n * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.\n * ------------------------------------------------------------------------------------------------------------------------------------\n *\n * This contract also supports private conversion between the converters:\n * Private conversions:\n * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between\n * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed\n * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.\n *\n * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first\n * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private\n * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:\n *\n * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.\n * tokenAddressOut: As base asset of that converter.\n *\n * ConverterNetwork:\n * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn\n * and tokenAddressOut provided.\n *\n * findTokenConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).\n *\n * findTokenConvertersForConverters():\n * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances\n * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).\n */\n\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\nabstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Maximum incentive could be\n uint256 public constant MAX_INCENTIVE = 0.5e18;\n\n /// @notice Min amount to convert for private conversions. Defined in USD, with 18 decimals\n uint256 public minAmountToConvert;\n\n /// @notice Venus price oracle contract\n ResilientOracle public priceOracle;\n\n /// @notice conversion configurations for the existing pairs\n /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig\n mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;\n\n /// @notice Address that all incoming tokens are transferred to\n address public destinationAddress;\n\n /// @notice Boolean for if conversion is paused\n bool public conversionPaused;\n\n /// @notice Address of the converterNetwork contract\n IConverterNetwork public converterNetwork;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n uint256[45] private __gap;\n\n /// @notice Emitted when config is updated for tokens pair\n event ConversionConfigUpdated(\n address indexed tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 oldIncentive,\n uint256 newIncentive,\n ConversionAccessibility oldAccess,\n ConversionAccessibility newAccess\n );\n /// @notice Emitted when price oracle address is updated\n event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);\n\n /// @notice Emitted when destination address is updated\n event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);\n\n /// @notice Emitted when converterNetwork address is updated\n event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);\n\n /// @notice Emitted when exact amount of tokens are converted for tokens\n event ConvertedExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens\n event ConvertedForExactTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens\n event ConvertedExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens\n event ConvertedForExactTokensSupportingFeeOnTransferTokens(\n address indexed sender,\n address indexed receiver,\n address tokenAddressIn,\n address indexed tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n );\n\n /// @notice Emitted when conversion is paused\n event ConversionPaused(address indexed sender);\n\n /// @notice Emitted when conversion is unpaused\n event ConversionResumed(address indexed sender);\n\n /// @notice Event emitted when tokens are swept\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens\n error AmountOutMismatched();\n\n /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens\n error AmountInMismatched();\n\n /// @notice Thrown when given input amount is zero\n error InsufficientInputAmount();\n\n /// @notice Thrown when given output amount is zero\n error InsufficientOutputAmount();\n\n /// @notice Thrown when conversion is disabled or config does not exist for given pair\n error ConversionConfigNotEnabled();\n\n /// @notice Thrown when conversion is enabled only for private conversions\n error ConversionEnabledOnlyForPrivateConversions();\n\n /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n error InvalidToAddress();\n\n /// @notice Thrown when incentive is higher than the MAX_INCENTIVE\n error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);\n\n /// @notice Thrown when amountOut is lower than amountOutMin\n error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);\n\n /// @notice Thrown when amountIn is higher than amountInMax\n error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);\n\n /// @notice Thrown when conversion is paused\n error ConversionTokensPaused();\n\n /// @notice Thrown when conversion is Active\n error ConversionTokensActive();\n\n /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination\n error InvalidTokenConfigAddresses();\n\n /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa\n error InsufficientPoolLiquidity();\n\n /// @notice When address of the ConverterNetwork is not set or Zero address\n error InvalidConverterNetwork();\n\n /// @notice Thrown when trying to set non zero incentive for private conversion\n error NonZeroIncentiveForPrivateConversion();\n\n /// @notice Thrown when using convertForExactTokens deflationary tokens\n error DeflationaryTokenNotSupported();\n\n /// @notice Thrown when minimum amount to convert is zero\n error InvalidMinimumAmountToConvert();\n\n /// @notice Thrown when there is a mismatch in the length of input arrays\n error InputLengthMisMatch();\n\n /**\n * @notice Modifier to ensure valid conversion parameters for a token conversion\n * and check if conversion is paused or not\n * @param to The recipient address for the converted tokens\n * @param tokenAddressIn The input token address for the conversion\n * @param tokenAddressOut The output token address for the conversion\n */\n modifier validConversionParameters(\n address to,\n address tokenAddressIn,\n address tokenAddressOut\n ) {\n _checkConversionPaused();\n ensureNonzeroAddress(to);\n if (to == tokenAddressIn || to == tokenAddressOut) {\n revert InvalidToAddress();\n }\n _;\n }\n\n /// @notice Pause conversion of tokens\n /// @custom:event Emits ConversionPaused on success\n /// @custom:error ConversionTokensPaused thrown when conversion is already paused\n /// @custom:access Restricted by ACM\n function pauseConversion() external {\n _checkAccessAllowed(\"pauseConversion()\");\n _checkConversionPaused();\n conversionPaused = true;\n emit ConversionPaused(msg.sender);\n }\n\n /// @notice Resume conversion of tokens.\n /// @custom:event Emits ConversionResumed on success\n /// @custom:error ConversionTokensActive thrown when conversion is already active\n /// @custom:access Restricted by ACM\n function resumeConversion() external {\n _checkAccessAllowed(\"resumeConversion()\");\n if (!conversionPaused) {\n revert ConversionTokensActive();\n }\n\n conversionPaused = false;\n emit ConversionResumed(msg.sender);\n }\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:access Only Governance\n function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {\n _setPriceOracle(priceOracle_);\n }\n\n /// @notice Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:access Only Governance\n function setDestination(address destinationAddress_) external onlyOwner {\n _setDestination(destinationAddress_);\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:access Only Governance\n function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {\n _setConverterNetwork(converterNetwork_);\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:access Only Governance\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n _setMinAmountToConvert(minAmountToConvert_);\n }\n\n /// @notice Batch sets the conversion configurations\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressesOut Array of addresses of tokenOut\n /// @param conversionConfigs Array of conversionConfig config details to update\n /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches\n function setConversionConfigs(\n address tokenAddressIn,\n address[] calldata tokenAddressesOut,\n ConversionConfig[] calldata conversionConfigs\n ) external {\n uint256 tokenOutArrayLength = tokenAddressesOut.length;\n if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();\n\n for (uint256 i; i < tokenOutArrayLength; ) {\n setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountIn != amountInMantissa) {\n revert AmountInMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,\n /// otherwise the amount is adjusted\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n if (actualAmountOut != amountOutMantissa) {\n revert AmountOutMismatched();\n }\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n }\n\n /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertExactTokens(\n amountInMantissa,\n amountOutMinMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of\n /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.\n /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount transferred to destination\n /// @return actualAmountOut Actual amount transferred to user\n /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero\n /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n )\n external\n validConversionParameters(to, tokenAddressIn, tokenAddressOut)\n nonReentrant\n returns (uint256 actualAmountIn, uint256 actualAmountOut)\n {\n (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(\n amountInMaxMantissa,\n amountOutMantissa,\n tokenAddressIn,\n tokenAddressOut,\n to\n );\n\n _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);\n emit ConvertedForExactTokensSupportingFeeOnTransferTokens(\n msg.sender,\n to,\n tokenAddressIn,\n tokenAddressOut,\n actualAmountIn,\n actualAmountOut\n );\n }\n\n /// @notice To sweep ERC20 tokens and transfer them to user(to address)\n /// @param tokenAddress The address of the ERC-20 token to sweep\n /// @param to The address to which tokens will be transferred\n /// @param amount The amount to transfer\n /// @custom:event Emits SweepToken event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\n /// @custom:access Only Governance\n function sweepToken(\n address tokenAddress,\n address to,\n uint256 amount\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(to);\n ensureNonzeroValue(amount);\n\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n preSweepToken(tokenAddress, amount);\n token.safeTransfer(to, amount);\n\n emit SweepToken(tokenAddress, to, amount);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @dev This function retrieves values without altering token prices\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n amountConvertedMantissa = amountInMantissa;\n uint256 tokenInToOutConversion;\n (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountConvertedMantissa =\n ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /\n tokenInToOutConversion; //round-up\n amountOutMantissa = maxTokenOutReserve;\n }\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.\n /// This function does not account for potential token transfer fees(in case of deflationary tokens)\n /// @dev This function retrieves values without altering token prices\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n if (\n conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountOutMantissa) {\n amountOutMantissa = maxTokenOutReserve;\n }\n\n amountConvertedMantissa = amountOutMantissa;\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountInMantissa;\n }\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {\n priceOracle.updateAssetPrice(tokenAddressIn);\n priceOracle.updateAssetPrice(tokenAddressOut);\n\n (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n amountConvertedMantissa = amountOutMantissa;\n }\n\n /// @notice This method updated the states of this contract after getting funds from PSR\n /// after settling the amount(if any) through privateConversion between converters\n /// @dev This function is called by protocolShareReserve\n /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then\n /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n function updateAssetsState(address comptroller, address asset) public nonReentrant {\n uint256 balanceDiff = _updateAssetsState(comptroller, asset);\n if (balanceDiff > 0) {\n _privateConversion(comptroller, asset, balanceDiff);\n }\n }\n\n /// @notice Set the configuration for new or existing conversion pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n /// @custom:event Emits ConversionConfigUpdated event on success\n /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion\n /// @custom:access Controlled by AccessControlManager\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) public {\n _checkAccessAllowed(\"setConversionConfig(address,address,ConversionConfig)\");\n ensureNonzeroAddress(tokenAddressIn);\n ensureNonzeroAddress(tokenAddressOut);\n\n if (conversionConfig.incentive > MAX_INCENTIVE) {\n revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);\n }\n\n if (\n (tokenAddressIn == tokenAddressOut) ||\n (tokenAddressIn != _getDestinationBaseAsset()) ||\n conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE\n ) {\n revert InvalidTokenConfigAddresses();\n }\n\n if (\n (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&\n conversionConfig.incentive != 0\n ) {\n revert NonZeroIncentiveForPrivateConversion();\n }\n\n if (\n ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||\n (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&\n (address(converterNetwork) == address(0))\n ) {\n revert InvalidConverterNetwork();\n }\n\n ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n emit ConversionConfigUpdated(\n tokenAddressIn,\n tokenAddressOut,\n configuration.incentive,\n conversionConfig.incentive,\n configuration.conversionAccess,\n conversionConfig.conversionAccess\n );\n\n if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {\n delete conversionConfigurations[tokenAddressIn][tokenAddressOut];\n } else {\n configuration.incentive = conversionConfig.incentive;\n configuration.conversionAccess = conversionConfig.conversionAccess;\n }\n }\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) public view virtual returns (uint256 tokenBalance);\n\n /// @dev Operations to perform before sweeping tokens\n /// @param token Address of the token\n /// @param amount Amount transferred to address(to)\n function preSweepToken(address token, uint256 amount) internal virtual {}\n\n /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return amountOutMantissa Actual amount of tokenAddressOut transferred\n /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa\n function _convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n if (amountOutMantissa < amountOutMinMantissa) {\n revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n }\n\n /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens\n /// it is called by convertForExactTokens function\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n if (actualAmountIn != amountInMantissa) {\n revert DeflationaryTokenNotSupported();\n }\n\n if (actualAmountIn > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n _doTransferOut(tokenAddressOut, to, amountOutMantissa);\n actualAmountOut = amountOutMantissa;\n }\n\n /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens\n /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @return actualAmountIn Actual amount of tokenAddressIn transferred\n /// @return actualAmountOut Actual amount of tokenAddressOut transferred\n /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa\n function _convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {\n _checkPrivateConversion(tokenAddressIn, tokenAddressOut);\n (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);\n\n if (amountInMantissa > amountInMaxMantissa) {\n revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);\n }\n\n actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);\n\n (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);\n\n _doTransferOut(tokenAddressOut, to, actualAmountOut);\n }\n\n /// @dev return actualAmountOut from reserves for tokenAddressOut\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param to Address of the tokenAddressOut receiver\n /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred\n /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa\n function _doTransferOut(\n address tokenAddressOut,\n address to,\n uint256 amountConvertedMantissa\n ) internal {\n uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);\n\n /// If contract has less liquidity for tokenAddressOut than amountOutMantissa\n if (maxTokenOutReserve < amountConvertedMantissa) {\n revert InsufficientPoolLiquidity();\n }\n\n _preTransferHook(tokenAddressOut, amountConvertedMantissa);\n\n IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);\n tokenOut.safeTransfer(to, amountConvertedMantissa);\n }\n\n /// @notice Transfer tokenAddressIn from user to destination\n /// @param tokenAddressIn Address of the token to convert\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @return actualAmountIn Actual amount transferred to destination\n function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {\n IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);\n uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);\n tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);\n uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);\n actualAmountIn = balanceAfterDestination - balanceBeforeDestination;\n }\n\n /// @dev Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n /// @custom:event Emits PriceOracleUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n function _setPriceOracle(ResilientOracle priceOracle_) internal {\n ensureNonzeroAddress(address(priceOracle_));\n emit PriceOracleUpdated(priceOracle, priceOracle_);\n priceOracle = priceOracle_;\n }\n\n /// @dev Sets a new destination address\n /// @param destinationAddress_ The new destination address to be set\n /// @custom:event Emits DestinationAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero\n function _setDestination(address destinationAddress_) internal {\n ensureNonzeroAddress(destinationAddress_);\n emit DestinationAddressUpdated(destinationAddress, destinationAddress_);\n destinationAddress = destinationAddress_;\n }\n\n /// @notice Sets a converter network contract address\n /// @param converterNetwork_ The converterNetwork address to be set\n /// @custom:event Emits ConverterNetworkAddressUpdated event on success\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {\n ensureNonzeroAddress(address(converterNetwork_));\n emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));\n converterNetwork = converterNetwork_;\n }\n\n /// @notice Min amount to convert setter\n /// @param minAmountToConvert_ Min amount to convert\n /// @custom:event MinAmountToConvertUpdated is emitted in success\n /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\n function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {\n ensureNonzeroValue(minAmountToConvert_);\n emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);\n minAmountToConvert = minAmountToConvert_;\n }\n\n /// @dev Hook to perform after converting tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @param amountIn Amount of tokenIn converted\n /// @param amountOut Amount of tokenOut converted\n function _postConversionHook(\n address tokenAddressIn,\n address tokenAddressOut,\n uint256 amountIn,\n uint256 amountOut\n ) internal virtual {}\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param minAmountToConvert_ minimum amount to convert\n function __AbstractTokenConverter_init_unchained(\n ResilientOracle priceOracle_,\n address destinationAddress_,\n uint256 minAmountToConvert_\n ) internal onlyInitializing {\n _setPriceOracle(priceOracle_);\n _setDestination(destinationAddress_);\n _setMinAmountToConvert(minAmountToConvert_);\n conversionPaused = false;\n }\n\n /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return Amount of asset, for _privateConversion\n function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}\n\n /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to\n /// destination contract as destination's base asset\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset\n /// @param amountToConvert Amount of the tokenAddressOut transferred to converter\n function _privateConversion(\n address comptroller,\n address tokenAddressOut,\n uint256 amountToConvert\n ) internal {\n address tokenAddressIn = _getDestinationBaseAsset();\n address _destinationAddress = destinationAddress;\n uint256 convertedTokenInBalance;\n if (address(converterNetwork) != address(0)) {\n (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork\n .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);\n uint256 convertersLength = converterAddresses.length;\n for (uint256 i; i < convertersLength; ) {\n if (converterBalances[i] == 0) break;\n (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(\n converterBalances[i],\n tokenAddressOut,\n tokenAddressIn\n );\n if (amountIn > amountToConvert) {\n amountIn = amountToConvert;\n }\n\n if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {\n break;\n }\n\n uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n\n IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);\n IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(\n amountIn,\n 0,\n tokenAddressOut,\n tokenAddressIn,\n _destinationAddress\n );\n\n uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);\n amountToConvert -= amountIn;\n convertedTokenInBalance += (balanceAfter - balanceBefore);\n\n if (amountToConvert == 0) break;\n unchecked {\n ++i;\n }\n }\n }\n\n _postPrivateConversionHook(\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance,\n tokenAddressOut,\n amountToConvert\n );\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal virtual {}\n\n /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}\n\n /// @dev Checks if amount to convert is greater than minimum amount to convert or not\n /// @param amountIn The amount to convert\n /// @param tokenAddress Address of the token\n /// @return isValid true if amount to convert is greater than minimum amount to convert\n function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {\n priceOracle.updateAssetPrice(tokenAddress);\n uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;\n\n if (amountInInUsd >= minAmountToConvert) {\n isValid = true;\n }\n }\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {\n if (amountInMantissa == 0) {\n revert InsufficientInputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n\n /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets\n /// multiplied by conversionWithIncentive which will be >= 1\n amountOutMantissa =\n (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /\n (tokenOutUnderlyingPrice * EXP_SCALE);\n\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n }\n\n /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function _getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {\n if (amountOutMantissa == 0) {\n revert InsufficientOutputAmount();\n }\n\n ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];\n\n if (configuration.conversionAccess == ConversionAccessibility.NONE) {\n revert ConversionConfigNotEnabled();\n }\n\n uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);\n uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);\n\n uint256 incentive = configuration.incentive;\n if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) {\n incentive = 0;\n }\n\n /// conversion rate after considering incentive(conversionWithIncentive)\n uint256 conversionWithIncentive = MANTISSA_ONE + incentive;\n tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;\n\n /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)\n amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up\n }\n\n /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion\n function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {\n bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);\n if (\n (!(isConverter) &&\n (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==\n ConversionAccessibility.ONLY_FOR_CONVERTERS))\n ) {\n revert ConversionEnabledOnlyForPrivateConversions();\n }\n }\n\n /// @dev To check, is conversion paused\n /// @custom:error ConversionTokensPaused is thrown when token conversion is paused\n function _checkConversionPaused() internal view {\n if (conversionPaused) {\n revert ConversionTokensPaused();\n }\n }\n\n /// @dev Get base asset address of the destination contract\n /// @return Address of the base asset\n function _getDestinationBaseAsset() internal view virtual returns (address) {}\n}\n" + }, + "contracts/TokenConverter/ConverterNetwork.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { sort } from \"../Utils/ArrayHelpers.sol\";\nimport { IAbstractTokenConverter } from \"./IAbstractTokenConverter.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @title ConverterNetwork\n/// @author Venus\n/// @notice ConverterNetwork keeps track of all the converters and is used to fetch valid converters which provide conversions according to token addresses provided\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract ConverterNetwork is IConverterNetwork, AccessControlledV8, MaxLoopsLimitHelper {\n /// @notice Array holding all the converters\n IAbstractTokenConverter[] public allConverters;\n\n /// @notice Emitted when new converter is added\n event ConverterAdded(address indexed converter);\n\n /// @notice Emitted when converter is removed\n event ConverterRemoved(address indexed converter);\n\n /// @notice Error thrown when converter already exists\n error ConverterAlreadyExists();\n\n /// @notice Error thrown converter does not exist\n error ConverterDoesNotExist();\n\n /// @notice Error thrown when converter address is invalid\n error InvalidTokenConverterAddress();\n\n /// @notice Error thrown when loops limit is invalid\n error InvalidMaxLoopsLimit(uint256 loopsLimit);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @notice ConverterNetwork initializer\n /// @param _accessControlManager The address of ACM contract\n /// @param _loopsLimit Limit for the loops in the contract to avoid DOS\n /// @custom:event ConverterAdded is emitted for each converter added on success\n /// @custom:error InvalidMaxLoopsLimit is thrown when when loops limit is invalid\n function initialize(address _accessControlManager, uint256 _loopsLimit) external initializer {\n ensureNonzeroAddress(_accessControlManager);\n __AccessControlled_init(_accessControlManager);\n\n if (_loopsLimit >= type(uint128).max) revert InvalidMaxLoopsLimit(_loopsLimit);\n _setMaxLoopsLimit(_loopsLimit);\n }\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param limit Limit for the max loops can execute at a time\n * @custom:error InvalidMaxLoopsLimit is thrown when when loops limit is invalid\n * @custom:access Only owner\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n if (limit >= type(uint128).max) revert InvalidMaxLoopsLimit(limit);\n _setMaxLoopsLimit(limit);\n }\n\n /// @notice Adds new converter to the array\n /// @param _tokenConverter Address of the token converter\n /// @custom:event ConverterAdded is emitted on success\n /// @custom:access Only Governance\n function addTokenConverter(IAbstractTokenConverter _tokenConverter) external {\n _checkAccessAllowed(\"addTokenConverter(address)\");\n _addTokenConverter(_tokenConverter);\n }\n\n /// @notice Removes converter from the array\n /// @param _tokenConverter Address of the token converter\n /// @custom:error ConverterDoesNotExist is thrown when converter to remove does not exist\n /// @custom:event ConverterRemoved is emitted on success\n /// @custom:access Only Governance\n function removeTokenConverter(IAbstractTokenConverter _tokenConverter) external {\n _checkAccessAllowed(\"removeTokenConverter(address)\");\n\n // Find the index of the converter in the array\n uint128 indexToRemove = _findConverterIndex(_tokenConverter);\n\n // Ensure that the converter exists in the array\n if (indexToRemove == type(uint128).max) revert ConverterDoesNotExist();\n\n // Swap the element to remove with the last element\n allConverters[indexToRemove] = allConverters[allConverters.length - 1];\n\n // Remove the last element (which is now a duplicate)\n allConverters.pop();\n\n emit ConverterRemoved(address(_tokenConverter));\n }\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// It will return the converters which are open to users for conversion\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance)\n {\n (converters, convertersBalance) = _findTokenConverters(_tokenAddressIn, _tokenAddressOut, false);\n }\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// It will return the converters which are open to converters for conversion.\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @return converters Array of the conveters on the basis of the tokens pair\n /// @return convertersBalance Array of balances with respect to token out\n function findTokenConvertersForConverters(address _tokenAddressIn, address _tokenAddressOut)\n external\n returns (address[] memory converters, uint256[] memory convertersBalance)\n {\n (converters, convertersBalance) = _findTokenConverters(_tokenAddressIn, _tokenAddressOut, true);\n }\n\n /// @notice This function returns the array containing all the converters addresses\n /// @return converters Array containing all the converters addresses\n function getAllConverters() external view returns (IAbstractTokenConverter[] memory converters) {\n converters = allConverters;\n }\n\n /// @notice This function checks if the given address is a converter or not\n /// @param _tokenConverter Address of the token converter\n /// @return isConverter true if given address is converter otherwise false\n function isTokenConverter(address _tokenConverter) external view returns (bool isConverter) {\n uint128 index = _findConverterIndex(IAbstractTokenConverter(_tokenConverter));\n\n if (index != type(uint128).max) {\n isConverter = true;\n }\n }\n\n /// @notice Adds new converter contract to the array\n /// @param _tokenConverter Address of the token converter\n /// @custom:error ConverterAlreadyExists is thrown when new tokenconverter to add already exists\n /// @custom:event ConverterAdded is emitted on success\n function _addTokenConverter(IAbstractTokenConverter _tokenConverter) internal {\n if (\n (address(_tokenConverter) == address(0)) || (address(_tokenConverter.converterNetwork()) != address(this))\n ) {\n revert InvalidTokenConverterAddress();\n }\n\n uint128 index = _findConverterIndex(_tokenConverter);\n if (index != type(uint128).max) revert ConverterAlreadyExists();\n\n allConverters.push(_tokenConverter);\n _ensureMaxLoops(allConverters.length);\n\n emit ConverterAdded(address(_tokenConverter));\n }\n\n /// @notice Used to get the array of converters supporting conversions, arranged in descending order based on token balances\n /// @param _tokenAddressIn Address of tokenIn\n /// @param _tokenAddressOut Address of tokenOut\n /// @param forConverters Bool to filter out converters on the basis of the conversionAccess\n /// @return converters Array of converters\n /// @return convertersBalance Array of balances with respect to token out\n function _findTokenConverters(\n address _tokenAddressIn,\n address _tokenAddressOut,\n bool forConverters\n ) internal returns (address[] memory converters, uint256[] memory convertersBalance) {\n uint128 convertersLength = uint128(allConverters.length);\n\n // Create a dynamic array to store the matching converters\n converters = new address[](convertersLength);\n convertersBalance = new uint256[](convertersLength);\n uint128 count;\n\n for (uint128 i; i < convertersLength; ) {\n IAbstractTokenConverter converter = allConverters[i];\n\n unchecked {\n ++i;\n }\n\n if ((address(converter.converterNetwork()) != address(this)) || msg.sender == address(converter)) {\n continue;\n }\n\n (, IAbstractTokenConverter.ConversionAccessibility conversionAccess) = converter.conversionConfigurations(\n _tokenAddressIn,\n _tokenAddressOut\n );\n\n if (conversionAccess == IAbstractTokenConverter.ConversionAccessibility.ALL) {\n converters[count] = address(converter);\n convertersBalance[count] = converter.balanceOf(_tokenAddressOut);\n ++count;\n } else if (\n forConverters &&\n (conversionAccess == IAbstractTokenConverter.ConversionAccessibility.ONLY_FOR_CONVERTERS)\n ) {\n converters[count] = address(converter);\n convertersBalance[count] = converter.balanceOf(_tokenAddressOut);\n ++count;\n } else if (\n !forConverters && (conversionAccess == IAbstractTokenConverter.ConversionAccessibility.ONLY_FOR_USERS)\n ) {\n converters[count] = address(converter);\n convertersBalance[count] = converter.balanceOf(_tokenAddressOut);\n ++count;\n }\n }\n\n // Resize the array to the actual number of matching converters\n assembly {\n mstore(converters, count)\n mstore(convertersBalance, count)\n }\n sort(convertersBalance, converters);\n }\n\n /// @notice Used to get the index of the converter stored in the array\n /// This will return the index if the converter exists in the array otherwise will return type(uint128).max\n /// @param _tokenConverter Address of the token converter\n /// @return index of the converter address in the allConverters array\n function _findConverterIndex(IAbstractTokenConverter _tokenConverter) internal view returns (uint128 index) {\n index = type(uint128).max; // Not found, return a large value\n\n uint128 convertersLength = uint128(allConverters.length);\n for (uint128 i; i < convertersLength; ) {\n if (allConverters[i] == _tokenConverter) {\n index = i;\n }\n unchecked {\n ++i;\n }\n }\n }\n}\n" + }, + "contracts/TokenConverter/IAbstractTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { IConverterNetwork } from \"../Interfaces/IConverterNetwork.sol\";\n\n/// @notice Interface for AbstractTokenConverter\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ninterface IAbstractTokenConverter {\n /// @notice This enum define the all possible ways of conversion can happen\n enum ConversionAccessibility {\n NONE, // Conversion is disable for the pair\n ALL, // Conversion is enable for private conversion and users\n ONLY_FOR_CONVERTERS, // Conversion is enable only for private conversion\n ONLY_FOR_USERS // Conversion is enable only for users\n }\n\n /// @notice This struct represents the configuration for a token conversion.\n struct ConversionConfig {\n /// incentive on conversion of tokens in mantissa i.e 10% incentive would be 0.1 * 1e18\n uint256 incentive;\n /// enable or disable conversion for users or converters or both or none\n ConversionAccessibility conversionAccess;\n }\n\n /// @notice Pause conversion of tokens\n function pauseConversion() external;\n\n /// @notice Resume conversion of tokens.\n function resumeConversion() external;\n\n /// @notice Sets a new price oracle\n /// @param priceOracle_ Address of the new price oracle to set\n function setPriceOracle(ResilientOracle priceOracle_) external;\n\n /// @notice Set the configuration for new or existing convert pair\n /// @param tokenAddressIn Address of tokenIn\n /// @param tokenAddressOut Address of tokenOut\n /// @param conversionConfig ConversionConfig config details to update\n function setConversionConfig(\n address tokenAddressIn,\n address tokenAddressOut,\n ConversionConfig calldata conversionConfig\n ) external;\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @dev Method does not support deflationary tokens transfer\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert exact amount of tokenAddressIn for tokenAddressOut\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMantissa,\n uint256 amountOutMinMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Convert tokens for tokenAddressIn for exact amount of tokenAddressOut\n /// @param amountInMaxMantissa Max amount of tokenAddressIn\n /// @param amountOutMantissa Amount of tokenAddressOut required as output\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after convert\n /// @param to Address of the tokenAddressOut receiver\n function convertForExactTokensSupportingFeeOnTransferTokens(\n uint256 amountInMaxMantissa,\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut,\n address to\n ) external returns (uint256 actualAmountIn, uint256 actualAmountOut);\n\n /// @notice Get the configuration for the pair of the tokens\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return incentives Percentage of incentives to be distributed for the pair of tokens\n /// @return conversionAccess Accessibility for the pair of tokens\n function conversionConfigurations(address tokenAddressIn, address tokenAddressOut)\n external\n returns (uint256 incentives, ConversionAccessibility conversionAccess);\n\n /// @notice Get the address of the converterNetwork\n function converterNetwork() external returns (IConverterNetwork converterNetwork);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getUpdatedAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut\n /// @dev This function retrieves values without altering token prices.\n /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion\n /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountIn(\n uint256 amountOutMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);\n\n /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn\n /// @dev This function retrieves values without altering token prices.\n /// @param amountInMantissa Amount of tokenAddressIn\n /// @param tokenAddressIn Address of the token to convert\n /// @param tokenAddressOut Address of the token to get after conversion\n /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion\n /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion\n /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero\n /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair\n function getAmountOut(\n uint256 amountInMantissa,\n address tokenAddressIn,\n address tokenAddressOut\n ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);\n\n /// @notice Get the balance for specific token\n /// @param token Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address token) external view returns (uint256 tokenBalance);\n}\n" + }, + "contracts/TokenConverter/RiskFundConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\nimport { IPoolRegistry } from \"../Interfaces/IPoolRegistry.sol\";\nimport { IComptroller } from \"../Interfaces/IComptroller.sol\";\nimport { IRiskFund, IRiskFundGetters } from \"../Interfaces/IRiskFund.sol\";\nimport { IVToken } from \"../Interfaces/IVToken.sol\";\n\n/// @title RiskFundConverter\n/// @author Venus\n/// @notice RiskFundConverter used for token conversions and sends received token to RiskFund\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract RiskFundConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the core pool comptroller\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n ///@notice Address of the vBNB\n ///@dev This address is used to include the BNB market while in getPools method\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable VBNB;\n\n ///@notice Address of the native wrapped currency\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_WRAPPED;\n\n /// @notice Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools)\n mapping(address => uint256) internal assetsReserves;\n\n /// @notice Store the asset's reserve per pool in the ProtocolShareReserve\n /// @dev Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal poolsAssetsReserves;\n\n /// @notice Address of pool registry contract\n address public poolRegistry;\n\n /// @notice The mapping contains the assets for each pool which are sent to RiskFund directly\n /// @dev Comptroller(pool) -> Asset -> bool(should transfer directly on true)\n mapping(address => mapping(address => bool)) public poolsAssetsDirectTransfer;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted after updating of the assets reserves\n /// amount -> reserve increased by amount\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @notice Emitted after the poolsAssetsDirectTransfer mapping is updated\n event PoolAssetsDirectTransferUpdated(address indexed comptroller, address indexed asset, bool value);\n\n // Error thrown when comptrollers array length is not equal to assets array length\n error InvalidArguments();\n\n /// @notice thrown when amount entered is greater than balance\n error InsufficientBalance();\n\n /// @notice thrown when asset does not exist in the pool\n error MarketNotExistInPool(address comptroller, address asset);\n\n /// @notice thrown to prevent reentrancy\n /// @dev This error is used to safeguard against reentrancy attacks, ensuring that a certain operation\n /// cannot be called recursively within the same transaction.\n error ReentrancyGuardError();\n\n /// @param corePoolComptroller_ Address of the Comptroller pool\n /// @param vBNB_ Address of the vBNB\n /// @param nativeWrapped_ Address of the wrapped native currency\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address corePoolComptroller_,\n address vBNB_,\n address nativeWrapped_\n ) {\n ensureNonzeroAddress(corePoolComptroller_);\n ensureNonzeroAddress(vBNB_);\n ensureNonzeroAddress(nativeWrapped_);\n\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\n VBNB = vBNB_;\n NATIVE_WRAPPED = nativeWrapped_;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param poolRegistry_ Address of the pool registry\n /// @param minAmountToConvert_ minimum amount to convert\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address poolRegistry_,\n uint256 minAmountToConvert_,\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) public initializer {\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n ensureNonzeroAddress(poolRegistry_);\n poolRegistry = poolRegistry_;\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Pool registry setter\n /// @param poolRegistry_ Address of the pool registry\n /// @custom:event PoolRegistryUpdated emits on success\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n /// @custom:access Only Governance\n function setPoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n emit PoolRegistryUpdated(poolRegistry, poolRegistry_);\n poolRegistry = poolRegistry_;\n }\n\n /// @notice Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:access Restricted by ACM\n function setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) external {\n _checkAccessAllowed(\"setPoolsAssetsDirectTransfer(address[],address[][],bool[][])\");\n _setPoolsAssetsDirectTransfer(comptrollers, assets, values);\n }\n\n /// @dev Get the Amount of the asset in the risk fund for the specific pool\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return reserves Asset's reserve in risk fund\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n /// @custom:error ReentrancyGuardError thrown to prevent reentrancy during the function execution\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256 reserves) {\n if (_reentrancyGuardEntered()) revert ReentrancyGuardError();\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n reserves = poolsAssetsReserves[comptroller][asset];\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Reserves of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n tokenBalance = assetsReserves[tokenAddress];\n }\n\n /// @notice Get the array of all pools addresses\n /// @param tokenAddress Address of the token\n /// @return poolsWithCore Array of the pools addresses in which token is available\n function getPools(address tokenAddress) public view returns (address[] memory poolsWithCore) {\n poolsWithCore = IPoolRegistry(poolRegistry).getPoolsSupportedByAsset(tokenAddress);\n\n if (isAssetListedInCore(tokenAddress)) {\n uint256 poolsLength = poolsWithCore.length;\n address[] memory extendedPools = new address[](poolsLength + 1);\n\n for (uint256 i; i < poolsLength; ) {\n extendedPools[i] = poolsWithCore[i];\n unchecked {\n ++i;\n }\n }\n\n extendedPools[poolsLength] = CORE_POOL_COMPTROLLER;\n poolsWithCore = extendedPools;\n }\n }\n\n /// @dev This hook is used to update the state for asset reserves before transferring tokenOut to user\n /// @param tokenOutAddress Address of the asset to be transferred to the user\n /// @param amountOut Amount of tokenAddressOut transferred from this converter\n function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal override {\n assetsReserves[tokenOutAddress] -= amountOut;\n }\n\n /// @notice Hook to perform after converting tokens\n /// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction\n /// @param tokenInAddress Address of the tokenIn\n /// @param tokenOutAddress Address of the tokenOut\n /// @param amountIn Amount of tokenIn transferred\n /// @param amountOut Amount of tokenOut transferred\n /// @custom:event AssetTransferredToDestination emits on success for each pool which has share\n function _postConversionHook(\n address tokenInAddress,\n address tokenOutAddress,\n uint256 amountIn,\n uint256 amountOut\n ) internal override {\n address[] memory pools = getPools(tokenOutAddress);\n uint256 assetReserve = assetsReserves[tokenOutAddress] + amountOut;\n ensureNonzeroValue(assetReserve);\n\n uint256 poolsLength = pools.length;\n uint256 distributedOutShare;\n uint256 poolAmountInShare;\n uint256 distributedInShare;\n\n for (uint256 i; i < poolsLength; ) {\n uint256 currentPoolsAssetsReserves = poolsAssetsReserves[pools[i]][tokenOutAddress];\n if (currentPoolsAssetsReserves != 0) {\n if (i < (poolsLength - 1)) {\n distributedOutShare += updatePoolAssetsReserve(pools[i], tokenOutAddress, amountOut, assetReserve);\n poolAmountInShare = (amountIn * currentPoolsAssetsReserves) / assetReserve;\n distributedInShare += poolAmountInShare;\n } else {\n uint256 distributedDiff = amountOut - distributedOutShare;\n poolsAssetsReserves[pools[i]][tokenOutAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenOutAddress, distributedDiff);\n poolAmountInShare = amountIn - distributedInShare;\n }\n emit AssetTransferredToDestination(destinationAddress, pools[i], tokenInAddress, poolAmountInShare);\n IRiskFund(destinationAddress).updatePoolState(pools[i], tokenInAddress, poolAmountInShare);\n }\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Operations to perform before sweeping tokens\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token\n function preSweepToken(address tokenAddress, uint256 amount) internal override {\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\n if (amount > balance) revert InsufficientBalance();\n uint256 balanceDiff = balance - assetsReserves[tokenAddress];\n\n if (balanceDiff < amount) {\n uint256 amountDiff;\n unchecked {\n amountDiff = amount - balanceDiff;\n }\n\n address[] memory pools = getPools(tokenAddress);\n uint256 assetReserve = assetsReserves[tokenAddress];\n uint256 poolsLength = pools.length;\n uint256 distributedShare;\n\n for (uint256 i; i < poolsLength; ) {\n if (poolsAssetsReserves[pools[i]][tokenAddress] != 0) {\n if (i < (poolsLength - 1)) {\n distributedShare += updatePoolAssetsReserve(pools[i], tokenAddress, amountDiff, assetReserve);\n } else {\n uint256 distributedDiff = amountDiff - distributedShare;\n poolsAssetsReserves[pools[i]][tokenAddress] -= distributedDiff;\n emit AssetsReservesUpdated(pools[i], tokenAddress, distributedDiff);\n }\n }\n unchecked {\n ++i;\n }\n }\n assetsReserves[tokenAddress] -= amountDiff;\n }\n }\n\n /// @dev Update the poolAssetsReserves upon transferring the tokens\n /// @param pool Address of the pool\n /// @param tokenAddress Address of the token\n /// @param amount Amount transferred to address(to)\n /// @param assetReserve Asset's reserve for the pool\n /// @return poolAmountShare Share of the pool as per it's reserve in compare to total reserves for the asset\n /// @custom:event AssetsReservesUpdated emits on success\n function updatePoolAssetsReserve(\n address pool,\n address tokenAddress,\n uint256 amount,\n uint256 assetReserve\n ) internal returns (uint256 poolAmountShare) {\n poolAmountShare = (poolsAssetsReserves[pool][tokenAddress] * amount) / assetReserve;\n poolsAssetsReserves[pool][tokenAddress] -= poolAmountShare;\n emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);\n }\n\n /// @dev Update the poolsAssetsDirectTransfer mapping\n /// @param comptrollers Addresses of the pools\n /// @param assets Addresses of the assets need to be added for direct transfer\n /// @param values Boolean value to indicate whether direct transfer is allowed for each asset.\n /// @custom:event PoolAssetsDirectTransferUpdated emits on success\n /// @custom:error InvalidArguments thrown when comptrollers array length is not equal to assets array length\n function _setPoolsAssetsDirectTransfer(\n address[] calldata comptrollers,\n address[][] calldata assets,\n bool[][] calldata values\n ) internal {\n uint256 comptrollersLength = comptrollers.length;\n\n if ((comptrollersLength != assets.length) || (comptrollersLength != values.length)) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < comptrollersLength; ) {\n address[] memory poolAssets = assets[i];\n bool[] memory assetsValues = values[i];\n uint256 poolAssetsLength = poolAssets.length;\n\n if (poolAssetsLength != assetsValues.length) {\n revert InvalidArguments();\n }\n\n for (uint256 j; j < poolAssetsLength; ) {\n poolsAssetsDirectTransfer[comptrollers[i]][poolAssets[j]] = assetsValues[j];\n emit PoolAssetsDirectTransferUpdated(comptrollers[i], poolAssets[j], assetsValues[j]);\n unchecked {\n ++j;\n }\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\n /// and transferring funds to the protocol share reserve\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address\n /// @return balanceDifference Amount of asset, for _privateConversion\n /// @custom:event AssetTransferredToDestination emits when poolsAssetsDirectTransfer is enabled for entered comptroller and asset\n /// @custom:error MarketNotExistInPool When asset does not exist in the pool(comptroller)\n function _updateAssetsState(address comptroller, address asset)\n internal\n override\n returns (uint256 balanceDifference)\n {\n if (!ensureAssetListed(comptroller, asset)) revert MarketNotExistInPool(comptroller, asset);\n\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 currentBalance = token.balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n if (poolsAssetsDirectTransfer[comptroller][asset]) {\n uint256 previousDestinationBalance = token.balanceOf(destinationAddress);\n token.safeTransfer(destinationAddress, balanceDifference);\n uint256 newDestinationBalance = token.balanceOf(destinationAddress);\n\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balanceDifference);\n IRiskFund(destinationAddress).updatePoolState(\n comptroller,\n asset,\n newDestinationBalance - previousDestinationBalance\n );\n balanceDifference = 0;\n }\n }\n }\n\n /// @dev This hook is used to update states for the converter after the privateConversion\n /// @param comptroller Comptroller address (pool)\n /// @param tokenAddressIn Address of the destination's base asset\n /// @param convertedTokenInBalance Amount of the base asset received after the conversion\n /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset\n /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter\n function _postPrivateConversionHook(\n address comptroller,\n address tokenAddressIn,\n uint256 convertedTokenInBalance,\n address tokenAddressOut,\n uint256 convertedTokenOutBalance\n ) internal override {\n if (convertedTokenInBalance > 0) {\n emit AssetTransferredToDestination(\n destinationAddress,\n comptroller,\n tokenAddressIn,\n convertedTokenInBalance\n );\n IRiskFund(destinationAddress).updatePoolState(comptroller, tokenAddressIn, convertedTokenInBalance);\n }\n if (convertedTokenOutBalance > 0) {\n assetsReserves[tokenAddressOut] += convertedTokenOutBalance;\n poolsAssetsReserves[comptroller][tokenAddressOut] += convertedTokenOutBalance;\n emit AssetsReservesUpdated(comptroller, tokenAddressOut, convertedTokenOutBalance);\n }\n }\n\n /// @dev This function checks for the given asset is listed in core pool or not\n /// @param tokenAddress Address of the asset\n /// @return isAssetListed true if the asset is listed\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\n address[] memory coreMarkets = IComptroller(CORE_POOL_COMPTROLLER).getAllMarkets();\n\n uint256 coreMarketsLength = coreMarkets.length;\n for (uint256 i; i < coreMarketsLength; ) {\n isAssetListed = (VBNB == coreMarkets[i])\n ? (tokenAddress == NATIVE_WRAPPED)\n : (IVToken(coreMarkets[i]).underlying() == tokenAddress);\n\n if (isAssetListed) {\n break;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev This function checks for the given asset is listed or not\n /// @param comptroller Address of the comptroller\n /// @param asset Address of the asset\n /// @return isListed true if the asset is listed\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool isListed) {\n if (comptroller == CORE_POOL_COMPTROLLER) {\n isListed = isAssetListedInCore(asset);\n } else {\n isListed = IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\n }\n }\n\n /// @dev Get base asset address of the RiskFund\n /// @return destinationBaseAsset Address of the base asset(RiskFund)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = IRiskFundGetters(destinationAddress).convertibleBaseAsset();\n }\n}\n" + }, + "contracts/TokenConverter/SingleTokenConverter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracle } from \"@venusprotocol/oracle/contracts/ResilientOracle.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { AbstractTokenConverter } from \"./AbstractTokenConverter.sol\";\n\n/// @title SingleTokenConverter\n/// @author Venus\n/// @notice SingleTokenConverter used for token conversions and sends received tokens\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\ncontract SingleTokenConverter is AbstractTokenConverter {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Address of the base asset token\n address public baseAsset;\n\n /// @notice Emitted when base asset is updated\n event BaseAssetUpdated(address indexed oldBaseAsset, address indexed newBaseAsset);\n\n /// @notice Emmitted after the funds transferred to the destination address\n event AssetTransferredToDestination(\n address indexed receiver,\n address indexed comptroller,\n address indexed asset,\n uint256 amount\n );\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @param accessControlManager_ Access control manager contract address\n /// @param priceOracle_ Resilient oracle address\n /// @param destinationAddress_ Address at all incoming tokens will transferred to\n /// @param baseAsset_ Address of the base asset\n /// @param minAmountToConvert_ Minimum amount to convert\n function initialize(\n address accessControlManager_,\n ResilientOracle priceOracle_,\n address destinationAddress_,\n address baseAsset_,\n uint256 minAmountToConvert_\n ) public initializer {\n _setBaseAsset(baseAsset_);\n\n // Initialize AbstractTokenConverter\n __AbstractTokenConverter_init(accessControlManager_, priceOracle_, destinationAddress_, minAmountToConvert_);\n }\n\n /// @notice Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:access Only Governance\n function setBaseAsset(address baseAsset_) external onlyOwner {\n _setBaseAsset(baseAsset_);\n }\n\n /// @notice Get the balance for specific token\n /// @param tokenAddress Address of the token\n /// @return tokenBalance Balance of the token the contract has\n function balanceOf(address tokenAddress) public view override returns (uint256 tokenBalance) {\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\n tokenBalance = token.balanceOf(address(this));\n }\n\n /// @param comptroller Comptroller address (pool)\n /// @param asset Asset address.\n /// @return balanceLeft Amount of asset, for _privateConversion\n // solhint-disable-next-line\n function _updateAssetsState(address comptroller, address asset) internal override returns (uint256 balanceLeft) {\n IERC20Upgradeable token = IERC20Upgradeable(asset);\n uint256 balance = token.balanceOf(address(this));\n balanceLeft = balance;\n\n if (asset == baseAsset) {\n balanceLeft = 0;\n token.safeTransfer(destinationAddress, balance);\n emit AssetTransferredToDestination(destinationAddress, comptroller, asset, balance);\n }\n }\n\n /// @dev Sets the base asset for the contract\n /// @param baseAsset_ The new address of the base asset\n /// @custom:error ZeroAddressNotAllowed is thrown when address is zero\n /// @custom:event BaseAssetUpdated is emitted on success\n function _setBaseAsset(address baseAsset_) internal {\n ensureNonzeroAddress(baseAsset_);\n emit BaseAssetUpdated(baseAsset, baseAsset_);\n baseAsset = baseAsset_;\n }\n\n /// @dev Get base asset address\n /// @return destinationBaseAsset Address of the base asset(baseAsset)\n function _getDestinationBaseAsset() internal view override returns (address destinationBaseAsset) {\n destinationBaseAsset = baseAsset;\n }\n}\n" + }, + "contracts/Utils/ArrayHelpers.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @notice Used to sort addresses array based on their token balances\n/// @param arr Array of token balances of different addresses\n/// @param addrs Array containing these addresses\nfunction sort(uint256[] memory arr, address[] memory addrs) pure {\n if (arr.length > 1) {\n return quickSortDescending(arr, addrs, 0, arr.length - 1);\n }\n}\n\n/// @notice Used to sort addresses array based on their token balances\n/// @param arr Array of token balances of different addresses\n/// @param addrs Array containing these addresses\n/// @param left index of first value\n/// @param right index of last value\nfunction quickSortDescending(\n uint256[] memory arr,\n address[] memory addrs,\n uint256 left,\n uint256 right\n) pure {\n if (left >= right) return;\n uint256 p = arr[(left + right) / 2]; // p = the pivot element\n uint256 i = left;\n uint256 j = right;\n while (i < j) {\n while (arr[i] > p) ++i;\n while (arr[j] < p) --j; // arr[j] < p means p still to the right, so j > 0\n if (arr[i] < arr[j]) {\n (arr[i], arr[j]) = (arr[j], arr[i]);\n (addrs[i], addrs[j]) = (addrs[j], addrs[i]);\n } else {\n ++i;\n }\n }\n\n if (j > left) quickSortDescending(arr, addrs, left, j - 1); // j > left, so j > 0\n quickSortDescending(arr, addrs, j + 1, right);\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} From eab12a84929160b7bf7994347f81b68bfa078d96 Mon Sep 17 00:00:00 2001 From: Jesus Lanchas Date: Thu, 29 Feb 2024 11:19:26 +0100 Subject: [PATCH 42/53] feat: upgrade dependencies and export opbnbmainnet addresses --- .github/workflows/ci.yml | 2 +- hardhat.config.ts | 12 + package.json | 5 +- yarn.lock | 567 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 556 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01ff14d6..05697232 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,7 +137,7 @@ jobs: - name: Export deployments run: | - for NETWORK in bsctestnet bscmainnet ethereum sepolia; do + for NETWORK in bsctestnet bscmainnet ethereum sepolia opbnbmainnet opbnbtestnet; do EXPORT=true yarn hardhat export --network ${NETWORK} --export ./deployments/${NETWORK}.json jq -M '{name, chainId, addresses: .contracts | map_values(.address)}' ./deployments/${NETWORK}.json > ./deployments/${NETWORK}_addresses.json done diff --git a/hardhat.config.ts b/hardhat.config.ts index a75463ff..15789b3d 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -32,11 +32,23 @@ const externalDeployments = { "node_modules/@venusprotocol/oracle/deployments/sepolia", "node_modules/@venusprotocol/isolated-pools/deployments/sepolia", ], + opbnbtestnet: [ + "node_modules/@venusprotocol/venus-protocol/deployments/opbnbtestnet", + "node_modules/@venusprotocol/governance-contracts/deployments/opbnbtestnet", + "node_modules/@venusprotocol/oracle/deployments/opbnbtestnet", + "node_modules/@venusprotocol/isolated-pools/deployments/opbnbtestnet", + ], bscmainnet: [ "node_modules/@venusprotocol/governance-contracts/deployments/bscmainnet", "node_modules/@venusprotocol/oracle/deployments/bscmainnet", "node_modules/@venusprotocol/isolated-pools/deployments/bscmainnet", ], + ethereum: [ + "node_modules/@venusprotocol/venus-protocol/deployments/ethereum", + "node_modules/@venusprotocol/governance-contracts/deployments/ethereum", + "node_modules/@venusprotocol/oracle/deployments/ethereum", + "node_modules/@venusprotocol/isolated-pools/deployments/ethereum", + ], opbnbmainnet: [ "node_modules/@venusprotocol/venus-protocol/deployments/opbnbmainnet", "node_modules/@venusprotocol/governance-contracts/deployments/opbnbmainnet", diff --git a/package.json b/package.json index 04e657db..c8e5162d 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "@openzeppelin/contracts-upgradeable": "^4.8.3", "@openzeppelin/hardhat-upgrades": "^1.21.0", "@solidity-parser/parser": "^0.13.2", - "@venusprotocol/isolated-pools": "^2.3.0", + "@venusprotocol/isolated-pools": "^2.6.0", "@venusprotocol/solidity-utilities": "^1.3.0", "ethers": "^5.7.0", "hardhat-deploy": "^0.11.14", @@ -71,7 +71,8 @@ "@typescript-eslint/eslint-plugin": "^5.44.0", "@typescript-eslint/parser": "^5.44.0", "@venusprotocol/governance-contracts": "^1.4.0", - "@venusprotocol/oracle": "^1.8.0", + "@venusprotocol/oracle": "^1.10.0", + "@venusprotocol/venus-protocol": "^7.3.0", "bignumber.js": "^9.1.1", "chai": "^4.3.7", "dotenv": "^16.0.3", diff --git a/yarn.lock b/yarn.lock index 2bbdc7f1..7fccb720 100644 --- a/yarn.lock +++ b/yarn.lock @@ -617,7 +617,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.0.9, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.6.3, @ethersproject/abi@npm:^5.7.0": +"@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.0.9, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.4.0, @ethersproject/abi@npm:^5.6.3, @ethersproject/abi@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abi@npm:5.7.0" dependencies: @@ -649,7 +649,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:5.7.0, @ethersproject/abstract-signer@npm:^5.7.0": +"@ethersproject/abstract-signer@npm:5.7.0, @ethersproject/abstract-signer@npm:^5.4.1, @ethersproject/abstract-signer@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abstract-signer@npm:5.7.0" dependencies: @@ -662,7 +662,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.7.0": +"@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.4.0, @ethersproject/address@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/address@npm:5.7.0" dependencies: @@ -694,7 +694,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.7.0": +"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.4.1, @ethersproject/bignumber@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bignumber@npm:5.7.0" dependencies: @@ -705,7 +705,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:^5.7.0": +"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:^5.4.0, @ethersproject/bytes@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bytes@npm:5.7.0" dependencies: @@ -714,7 +714,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/constants@npm:5.7.0, @ethersproject/constants@npm:^5.7.0": +"@ethersproject/constants@npm:5.7.0, @ethersproject/constants@npm:^5.4.0, @ethersproject/constants@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/constants@npm:5.7.0" dependencies: @@ -723,7 +723,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/contracts@npm:5.7.0, @ethersproject/contracts@npm:^5.7.0": +"@ethersproject/contracts@npm:5.7.0, @ethersproject/contracts@npm:^5.4.1, @ethersproject/contracts@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/contracts@npm:5.7.0" dependencies: @@ -844,7 +844,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.7.0, @ethersproject/providers@npm:^5.7.1, @ethersproject/providers@npm:^5.7.2": +"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.4.4, @ethersproject/providers@npm:^5.7.0, @ethersproject/providers@npm:^5.7.1, @ethersproject/providers@npm:^5.7.2": version: 5.7.2 resolution: "@ethersproject/providers@npm:5.7.2" dependencies: @@ -917,7 +917,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/solidity@npm:5.7.0, @ethersproject/solidity@npm:^5.7.0": +"@ethersproject/solidity@npm:5.7.0, @ethersproject/solidity@npm:^5.4.0, @ethersproject/solidity@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/solidity@npm:5.7.0" dependencies: @@ -942,7 +942,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/transactions@npm:5.7.0, @ethersproject/transactions@npm:^5.7.0": +"@ethersproject/transactions@npm:5.7.0, @ethersproject/transactions@npm:^5.4.0, @ethersproject/transactions@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/transactions@npm:5.7.0" dependencies: @@ -970,7 +970,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/wallet@npm:5.7.0, @ethersproject/wallet@npm:^5.7.0": +"@ethersproject/wallet@npm:5.7.0, @ethersproject/wallet@npm:^5.4.0, @ethersproject/wallet@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/wallet@npm:5.7.0" dependencies: @@ -1131,6 +1131,36 @@ __metadata: languageName: node linkType: hard +"@layerzerolabs/lz-evm-sdk-v1-0.7@npm:^1.5.14": + version: 1.5.16 + resolution: "@layerzerolabs/lz-evm-sdk-v1-0.7@npm:1.5.16" + dependencies: + "@openzeppelin/contracts": 3.4.2-solc-0.7 + "@openzeppelin/contracts-upgradeable": 3.4.2-solc-0.7 + checksum: c4a42f446fe4c961bdfc5cbdd848b98ba1f2352ddd539d04affba7d9760905b0604a3422a1a9a7e89808466e6fcbb05e40498948b663beb21e47127b00d9cd9f + languageName: node + linkType: hard + +"@layerzerolabs/solidity-examples@npm:^1.0.0": + version: 1.1.0 + resolution: "@layerzerolabs/solidity-examples@npm:1.1.0" + dependencies: + "@layerzerolabs/lz-evm-sdk-v1-0.7": ^1.5.14 + "@openzeppelin-3/contracts": "npm:@openzeppelin/contracts@^3.4.2-solc-0.7" + "@openzeppelin/contracts": ^4.4.1 + "@openzeppelin/contracts-upgradeable": ^4.6.0 + "@openzeppelin/hardhat-upgrades": ^1.18.3 + dotenv: ^10.0.0 + erc721a: ^4.2.3 + hardhat: ^2.8.0 + hardhat-contract-sizer: ^2.1.1 + hardhat-deploy: ^0.10.5 + hardhat-deploy-ethers: ^0.3.0-beta.13 + hardhat-gas-reporter: ^1.0.6 + checksum: f7603710b18bdda227024b161059b5f725499529d25ea2c6dc7a16c664f2b25bd2be2761e81e870a08b05013c425bf7b5258e7a667ac9390cf598c043b216407 + languageName: node + linkType: hard + "@metamask/eth-sig-util@npm:^4.0.0": version: 4.0.1 resolution: "@metamask/eth-sig-util@npm:4.0.1" @@ -1237,6 +1267,20 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-block@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-block@npm:5.0.4" + dependencies: + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-trie": 6.0.4 + "@nomicfoundation/ethereumjs-tx": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + ethereum-cryptography: 0.1.3 + checksum: fe60b3dc31e0991eb6659f838485384e52992b72dd97a42c7bec320ea9902d1200352b5690a222442f77c5447cee4dd834fc25c53247aed5aa3130b0ab7e3c53 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-blockchain@npm:6.2.2": version: 6.2.2 resolution: "@nomicfoundation/ethereumjs-blockchain@npm:6.2.2" @@ -1278,6 +1322,24 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-blockchain@npm:7.0.4": + version: 7.0.4 + resolution: "@nomicfoundation/ethereumjs-blockchain@npm:7.0.4" + dependencies: + "@nomicfoundation/ethereumjs-block": 5.0.4 + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-ethash": 3.0.4 + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-trie": 6.0.4 + "@nomicfoundation/ethereumjs-tx": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + debug: ^4.3.3 + ethereum-cryptography: 0.1.3 + lru-cache: ^10.0.0 + checksum: 0d35f28ed5ef356557b974b91898b6f61292a3e0fd3d1b1c8924250a59c7f583939453184f5b54f7cd2a2d8c055cdc6f3b8588c7b22f839beaa4ba69638ba2c8 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-common@npm:3.1.2": version: 3.1.2 resolution: "@nomicfoundation/ethereumjs-common@npm:3.1.2" @@ -1298,6 +1360,15 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-common@npm:4.0.4": + version: 4.0.4 + resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.4" + dependencies: + "@nomicfoundation/ethereumjs-util": 9.0.4 + checksum: ce3f6e4ae15b976efdb7ccda27e19aadb62b5ffee209f9503e68b4fd8633715d4d697c0cc10ccd35f5e4e977edd05100d0f214e28880ec64fff77341dc34fcdf + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-ethash@npm:2.0.5": version: 2.0.5 resolution: "@nomicfoundation/ethereumjs-ethash@npm:2.0.5" @@ -1326,6 +1397,19 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-ethash@npm:3.0.4": + version: 3.0.4 + resolution: "@nomicfoundation/ethereumjs-ethash@npm:3.0.4" + dependencies: + "@nomicfoundation/ethereumjs-block": 5.0.4 + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + bigint-crypto-utils: ^3.2.2 + ethereum-cryptography: 0.1.3 + checksum: 52c2b003078be233929ae8355e8d2e0949ac66f75312a47725790b87111293de4303750a446f10eec22f5ffd9a2accb3f17fff8e6a85c36b47786e25242dad66 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-evm@npm:1.3.2, @nomicfoundation/ethereumjs-evm@npm:^1.0.0-rc.3": version: 1.3.2 resolution: "@nomicfoundation/ethereumjs-evm@npm:1.3.2" @@ -1358,6 +1442,22 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-evm@npm:2.0.4": + version: 2.0.4 + resolution: "@nomicfoundation/ethereumjs-evm@npm:2.0.4" + dependencies: + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-statemanager": 2.0.4 + "@nomicfoundation/ethereumjs-tx": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + "@types/debug": ^4.1.9 + debug: ^4.3.3 + ethereum-cryptography: 0.1.3 + rustbn-wasm: ^0.2.0 + checksum: db25327f7bda067cd0726a1bc7937c1c0405602fbe692abaa804f44e4fe9d2dcce103d50a767c0f3dc3067b38c35f468e997789234d2a4aef0ad31a36ad6d916 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-rlp@npm:4.0.3": version: 4.0.3 resolution: "@nomicfoundation/ethereumjs-rlp@npm:4.0.3" @@ -1376,6 +1476,15 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-rlp@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-rlp@npm:5.0.4" + bin: + rlp: bin/rlp.cjs + checksum: ee2c2e5776c73801dc5ed636f4988b599b4563c2d0037da542ea57eb237c69dd1ac555f6bcb5e06f70515b6459779ba0d68252a6e105132b4659ab4bf62919b0 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-statemanager@npm:1.0.5": version: 1.0.5 resolution: "@nomicfoundation/ethereumjs-statemanager@npm:1.0.5" @@ -1405,6 +1514,27 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-statemanager@npm:2.0.4": + version: 2.0.4 + resolution: "@nomicfoundation/ethereumjs-statemanager@npm:2.0.4" + dependencies: + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-trie": 6.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + debug: ^4.3.3 + ethereum-cryptography: 0.1.3 + js-sdsl: ^4.1.4 + lru-cache: ^10.0.0 + peerDependencies: + "@nomicfoundation/ethereumjs-verkle": 0.0.2 + peerDependenciesMeta: + "@nomicfoundation/ethereumjs-verkle": + optional: true + checksum: 585dc67872d37f39310d85fc5c1b3179691412b9450411422ad6468017d8723e5192d22447c927d8403f7b6e95c1ecf7b48467edc440e50f15b5ac81e1fecd1d + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-trie@npm:5.0.5": version: 5.0.5 resolution: "@nomicfoundation/ethereumjs-trie@npm:5.0.5" @@ -1430,6 +1560,20 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-trie@npm:6.0.4": + version: 6.0.4 + resolution: "@nomicfoundation/ethereumjs-trie@npm:6.0.4" + dependencies: + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + "@types/readable-stream": ^2.3.13 + ethereum-cryptography: 0.1.3 + lru-cache: ^10.0.0 + readable-stream: ^3.6.0 + checksum: 93a6be32657e67e74714fe557dbaf606d92c5cd1571c60f249295c27b0ab24b64e2e59cf211c214f8ba403d6475d23ed8c557be9077b92b2317e44384de8a6bf + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-tx@npm:4.1.2": version: 4.1.2 resolution: "@nomicfoundation/ethereumjs-tx@npm:4.1.2" @@ -1456,6 +1600,23 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-tx@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-tx@npm:5.0.4" + dependencies: + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + ethereum-cryptography: 0.1.3 + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + checksum: 0f1c87716682ccbcf4d92ffc6cf8ab557e658b90319d82be3219a091a736859f8803c73c98e4863682e3e86d264751c472d33ff6d3c3daf4e75b5f01d0af8fa3 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-util@npm:8.0.6, @nomicfoundation/ethereumjs-util@npm:^8.0.0-rc.3": version: 8.0.6 resolution: "@nomicfoundation/ethereumjs-util@npm:8.0.6" @@ -1477,6 +1638,33 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-util@npm:9.0.4": + version: 9.0.4 + resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.4" + dependencies: + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + ethereum-cryptography: 0.1.3 + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + checksum: 754439f72b11cad2d8986707ad020077dcc763c4055f73e2668a0b4cadb22aa4407faa9b3c587d9eb5b97ac337afbe037eb642bc1d5a16197284f83db3462cbe + languageName: node + linkType: hard + +"@nomicfoundation/ethereumjs-verkle@npm:0.0.2": + version: 0.0.2 + resolution: "@nomicfoundation/ethereumjs-verkle@npm:0.0.2" + dependencies: + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + lru-cache: ^10.0.0 + rust-verkle-wasm: ^0.0.1 + checksum: e075d7a2475670bb7039e715f0edce849ef3947aae2c7d0b658f058686ac9df3863499a5324717beff5d8f20a751f85ba1449942af818ec6772d775dcbb011d6 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-vm@npm:7.0.2": version: 7.0.2 resolution: "@nomicfoundation/ethereumjs-vm@npm:7.0.2" @@ -1498,6 +1686,25 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-vm@npm:7.0.4": + version: 7.0.4 + resolution: "@nomicfoundation/ethereumjs-vm@npm:7.0.4" + dependencies: + "@nomicfoundation/ethereumjs-block": 5.0.4 + "@nomicfoundation/ethereumjs-blockchain": 7.0.4 + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-evm": 2.0.4 + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-statemanager": 2.0.4 + "@nomicfoundation/ethereumjs-trie": 6.0.4 + "@nomicfoundation/ethereumjs-tx": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + debug: ^4.3.3 + ethereum-cryptography: 0.1.3 + checksum: 6f3b2507189b236e65dd3eaf3f072385a0252b826a348fe6ea5532a810bc2b6aab11d8ccec2cdfed629995e61e4c82c6e8765ac5794154772064ba3f18397407 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-vm@npm:^6.0.0-rc.3": version: 6.4.2 resolution: "@nomicfoundation/ethereumjs-vm@npm:6.4.2" @@ -2075,6 +2282,27 @@ __metadata: languageName: node linkType: hard +"@openzeppelin-3/contracts@npm:@openzeppelin/contracts@^3.4.2-solc-0.7, @openzeppelin/contracts-v0.7@npm:@openzeppelin/contracts@v3.4.2": + version: 3.4.2 + resolution: "@openzeppelin/contracts@npm:3.4.2" + checksum: 0c90f029fe50a49643588e4c8670dae3bbf31795133a6ddce9bdcbc258486332700bb732287baabf7bf807f39182fe8ea2ffa19aa5caf359b1b9c0f083280748 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:3.4.2-solc-0.7": + version: 3.4.2-solc-0.7 + resolution: "@openzeppelin/contracts-upgradeable@npm:3.4.2-solc-0.7" + checksum: 662d168ea1763faa5e168751043e4e041ccd810c3d4c781aa5aee0e9947e9f95d51edaeb1daaa4cc2860463beb961b576c6a3e60e3fbb6fa27188a611c8522e4 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:^4.6.0": + version: 4.9.5 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.5" + checksum: d5d9bad93fe2a88a8336060901d45f185ebfe1fed9844b1fe50e8641d946588c6e69a5a8f1694f0bd073c913b4b9a5c34316acfc17d8f75228adecbcb635ea62 + languageName: node + linkType: hard + "@openzeppelin/contracts-upgradeable@npm:^4.7.3, @openzeppelin/contracts-upgradeable@npm:^4.8.0, @openzeppelin/contracts-upgradeable@npm:^4.8.3": version: 4.9.3 resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.3" @@ -2082,10 +2310,10 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/contracts-v0.7@npm:@openzeppelin/contracts@v3.4.2": - version: 3.4.2 - resolution: "@openzeppelin/contracts@npm:3.4.2" - checksum: 0c90f029fe50a49643588e4c8670dae3bbf31795133a6ddce9bdcbc258486332700bb732287baabf7bf807f39182fe8ea2ffa19aa5caf359b1b9c0f083280748 +"@openzeppelin/contracts@npm:3.4.2-solc-0.7": + version: 3.4.2-solc-0.7 + resolution: "@openzeppelin/contracts@npm:3.4.2-solc-0.7" + checksum: 1a6048f31ed560c34429a05e534102c51124ecaf113aca7ebeb7897cfaaf61007cdd7952374c282adaeb79b04ee86ee80b16eed28b62fc6d60e3ffcd7a696895 languageName: node linkType: hard @@ -2096,6 +2324,13 @@ __metadata: languageName: node linkType: hard +"@openzeppelin/contracts@npm:^4.4.1": + version: 4.9.5 + resolution: "@openzeppelin/contracts@npm:4.9.5" + checksum: 2cddeb08c006a8f99c5cc40cc80aecb449fd941cd1a92ebda315d77f48c4b4d487798a1254bffbc3ec811b390365d14665e92dbb2dd8f45aacef479d69d94574 + languageName: node + linkType: hard + "@openzeppelin/defender-base-client@npm:^1.46.0": version: 1.52.0 resolution: "@openzeppelin/defender-base-client@npm:1.52.0" @@ -2109,7 +2344,7 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/hardhat-upgrades@npm:^1.21.0": +"@openzeppelin/hardhat-upgrades@npm:^1.18.3, @openzeppelin/hardhat-upgrades@npm:^1.21.0": version: 1.28.0 resolution: "@openzeppelin/hardhat-upgrades@npm:1.28.0" dependencies: @@ -2198,6 +2433,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:^1.1.1": + version: 1.1.5 + resolution: "@scure/base@npm:1.1.5" + checksum: 9e9ee6088cb3aa0fb91f5a48497d26682c7829df3019b1251d088d166d7a8c0f941c68aaa8e7b96bbad20c71eb210397cb1099062cde3e29d4bad6b975c18519 + languageName: node + linkType: hard + "@scure/base@npm:~1.1.0": version: 1.1.3 resolution: "@scure/base@npm:1.1.3" @@ -2628,6 +2870,15 @@ __metadata: languageName: node linkType: hard +"@types/debug@npm:^4.1.9": + version: 4.1.12 + resolution: "@types/debug@npm:4.1.12" + dependencies: + "@types/ms": "*" + checksum: 47876a852de8240bfdaf7481357af2b88cb660d30c72e73789abf00c499d6bc7cd5e52f41c915d1b9cd8ec9fef5b05688d7b7aef17f7f272c2d04679508d1053 + languageName: node + linkType: hard + "@types/events@npm:*": version: 3.0.3 resolution: "@types/events@npm:3.0.3" @@ -2696,6 +2947,13 @@ __metadata: languageName: node linkType: hard +"@types/ms@npm:*": + version: 0.7.34 + resolution: "@types/ms@npm:0.7.34" + checksum: f38d36e7b6edecd9badc9cf50474159e9da5fa6965a75186cceaf883278611b9df6669dc3a3cc122b7938d317b68a9e3d573d316fcb35d1be47ec9e468c6bd8a + languageName: node + linkType: hard + "@types/node@npm:*": version: 20.10.0 resolution: "@types/node@npm:20.10.0" @@ -2953,9 +3211,25 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/oracle@npm:^1.8.0": - version: 1.9.0 - resolution: "@venusprotocol/oracle@npm:1.9.0" +"@venusprotocol/isolated-pools@npm:^2.5.0, @venusprotocol/isolated-pools@npm:^2.6.0": + version: 2.6.0 + resolution: "@venusprotocol/isolated-pools@npm:2.6.0" + dependencies: + "@nomiclabs/hardhat-ethers": ^2.2.3 + "@openzeppelin/contracts": ^4.8.3 + "@openzeppelin/contracts-upgradeable": ^4.8.3 + "@openzeppelin/hardhat-upgrades": ^1.21.0 + "@solidity-parser/parser": ^0.13.2 + ethers: ^5.7.0 + hardhat-deploy: ^0.11.14 + module-alias: ^2.2.2 + checksum: 324bdaa9d6de3f812800f78429d4f35812fc5d71a9127b6c6726e5f7b20924b074d5ed2935cf0c4977f0db053624ad9ba27e9207184bcd4672dd9ead3986ba12 + languageName: node + linkType: hard + +"@venusprotocol/oracle@npm:^1.10.0": + version: 1.10.0 + resolution: "@venusprotocol/oracle@npm:1.10.0" dependencies: "@chainlink/contracts": ^0.5.1 "@defi-wonderland/smock": ^2.3.4 @@ -2970,11 +3244,11 @@ __metadata: hardhat-deploy: ^0.11.14 module-alias: ^2.2.2 solidity-docgen: ^0.6.0-beta.29 - checksum: 60995054e5cb3e970e940afa04e49cc06a8150584be5b777dc559766fef5e4e9ab1acbff1b9158c8e4241f45080dc576050373d1de57768868d1d16710f7469a + checksum: 44de308a3ba728e094b11de0da776dc53690601e9e462c83c087c6c3cb8cedb49d2b4cdda4c8a6dc215d9884369a3e99b11fed1d41d4fe9108d35fc7ff0e893d languageName: node linkType: hard -"@venusprotocol/protocol-reserve@npm:^1.1.0": +"@venusprotocol/protocol-reserve@npm:^1.1.0, @venusprotocol/protocol-reserve@npm:^1.4.0": version: 1.4.0 resolution: "@venusprotocol/protocol-reserve@npm:1.4.0" dependencies: @@ -3020,9 +3294,10 @@ __metadata: "@typescript-eslint/eslint-plugin": ^5.44.0 "@typescript-eslint/parser": ^5.44.0 "@venusprotocol/governance-contracts": ^1.4.0 - "@venusprotocol/isolated-pools": ^2.3.0 - "@venusprotocol/oracle": ^1.8.0 + "@venusprotocol/isolated-pools": ^2.6.0 + "@venusprotocol/oracle": ^1.10.0 "@venusprotocol/solidity-utilities": ^1.3.0 + "@venusprotocol/venus-protocol": ^7.3.0 bignumber.js: ^9.1.1 chai: ^4.3.7 dotenv: ^16.0.3 @@ -3067,6 +3342,21 @@ __metadata: languageName: node linkType: hard +"@venusprotocol/token-bridge@npm:1.0.0": + version: 1.0.0 + resolution: "@venusprotocol/token-bridge@npm:1.0.0" + dependencies: + "@layerzerolabs/solidity-examples": ^1.0.0 + "@openzeppelin/contracts": ^4.8.3 + "@openzeppelin/contracts-upgradeable": ^4.8.3 + "@openzeppelin/hardhat-upgrades": ^1.21.0 + "@solidity-parser/parser": ^0.13.2 + ethers: ^5.7.0 + module-alias: ^2.2.2 + checksum: fa494157cc2493bcb4b2824fd545f2093b459404a449da6710c3c62ebd2638abc42cd15a06f60a7d537eb30e7e2efeab90961e34a60ecfef5d9c33c8e26b9405 + languageName: node + linkType: hard + "@venusprotocol/venus-protocol@npm:^6.0.0": version: 6.0.0 resolution: "@venusprotocol/venus-protocol@npm:6.0.0" @@ -3082,6 +3372,24 @@ __metadata: languageName: node linkType: hard +"@venusprotocol/venus-protocol@npm:^7.3.0": + version: 7.3.0 + resolution: "@venusprotocol/venus-protocol@npm:7.3.0" + dependencies: + "@openzeppelin/contracts": 4.9.3 + "@openzeppelin/contracts-upgradeable": ^4.8.0 + "@venusprotocol/governance-contracts": ^1.4.0 + "@venusprotocol/isolated-pools": ^2.5.0 + "@venusprotocol/protocol-reserve": ^1.4.0 + "@venusprotocol/solidity-utilities": ^1.2.0 + "@venusprotocol/token-bridge": 1.0.0 + bignumber.js: ^9.1.2 + dotenv: ^16.0.1 + module-alias: ^2.2.2 + checksum: 2f277fca454a839471a7ddb09d5725e5eef2d974076acbeca461bff7209c041e9f39fdbcc1fd49832b77f2539ae83c438e6fdddb3a267552bcb4a08fbaa2bd92 + languageName: node + linkType: hard + "JSONStream@npm:^1.0.4, JSONStream@npm:^1.3.5": version: 1.3.5 resolution: "JSONStream@npm:1.3.5" @@ -3257,6 +3565,15 @@ __metadata: languageName: node linkType: hard +"ansi-align@npm:^3.0.0": + version: 3.0.1 + resolution: "ansi-align@npm:3.0.1" + dependencies: + string-width: ^4.1.0 + checksum: 6abfa08f2141d231c257162b15292467081fa49a208593e055c866aa0455b57f3a86b5a678c190c618faa79b4c59e254493099cb700dd9cf2293c6be2c8f5d8d + languageName: node + linkType: hard + "ansi-colors@npm:4.1.1": version: 4.1.1 resolution: "ansi-colors@npm:4.1.1" @@ -3703,7 +4020,7 @@ __metadata: languageName: node linkType: hard -"bigint-crypto-utils@npm:^3.0.23": +"bigint-crypto-utils@npm:^3.0.23, bigint-crypto-utils@npm:^3.2.2": version: 3.3.0 resolution: "bigint-crypto-utils@npm:3.3.0" checksum: 9598ce57b23f776c8936d44114c9f051e62b5fa654915b664784cbcbacc5aa0485f4479571c51ff58008abb1210c0d6a234853742f07cf84bda890f2a1e01000 @@ -3773,6 +4090,22 @@ __metadata: languageName: node linkType: hard +"boxen@npm:^5.1.2": + version: 5.1.2 + resolution: "boxen@npm:5.1.2" + dependencies: + ansi-align: ^3.0.0 + camelcase: ^6.2.0 + chalk: ^4.1.0 + cli-boxes: ^2.2.1 + string-width: ^4.2.2 + type-fest: ^0.20.2 + widest-line: ^3.1.0 + wrap-ansi: ^7.0.0 + checksum: 82d03e42a72576ff235123f17b7c505372fe05c83f75f61e7d4fa4bcb393897ec95ce766fecb8f26b915f0f7a7227d66e5ec7cef43f5b2bd9d3aeed47ec55877 + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -4015,7 +4348,7 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^6.0.0": +"camelcase@npm:^6.0.0, camelcase@npm:^6.2.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" checksum: 8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d @@ -4216,6 +4549,13 @@ __metadata: languageName: node linkType: hard +"cli-boxes@npm:^2.2.1": + version: 2.2.1 + resolution: "cli-boxes@npm:2.2.1" + checksum: be79f8ec23a558b49e01311b39a1ea01243ecee30539c880cf14bf518a12e223ef40c57ead0cb44f509bffdffc5c129c746cd50d863ab879385370112af4f585 + languageName: node + linkType: hard + "cli-columns@npm:^4.0.0": version: 4.0.0 resolution: "cli-columns@npm:4.0.0" @@ -4240,7 +4580,7 @@ __metadata: languageName: node linkType: hard -"cli-table3@npm:^0.6.2, cli-table3@npm:^0.6.3": +"cli-table3@npm:^0.6.0, cli-table3@npm:^0.6.2, cli-table3@npm:^0.6.3": version: 0.6.3 resolution: "cli-table3@npm:0.6.3" dependencies: @@ -4984,6 +5324,13 @@ __metadata: languageName: node linkType: hard +"dotenv@npm:^10.0.0": + version: 10.0.0 + resolution: "dotenv@npm:10.0.0" + checksum: f412c5fe8c24fbe313d302d2500e247ba8a1946492db405a4de4d30dd0eb186a88a43f13c958c5a7de303938949c4231c56994f97d05c4bc1f22478d631b4005 + languageName: node + linkType: hard + "dotenv@npm:^16.0.1, dotenv@npm:^16.0.3": version: 16.3.1 resolution: "dotenv@npm:16.3.1" @@ -5080,6 +5427,13 @@ __metadata: languageName: node linkType: hard +"erc721a@npm:^4.2.3": + version: 4.2.3 + resolution: "erc721a@npm:4.2.3" + checksum: 0b2223678219d9b4a228da880cca9aab396ebe9cb59baf34a5501d4d9d297024d492ee5335c1983cd4c3bd15deef5e162c4837d27ac5ab5bf66e01591ead425c + languageName: node + linkType: hard + "err-code@npm:^2.0.2": version: 2.0.3 resolution: "err-code@npm:2.0.3" @@ -6510,6 +6864,19 @@ __metadata: languageName: node linkType: hard +"hardhat-contract-sizer@npm:^2.1.1": + version: 2.10.0 + resolution: "hardhat-contract-sizer@npm:2.10.0" + dependencies: + chalk: ^4.0.0 + cli-table3: ^0.6.0 + strip-ansi: ^6.0.0 + peerDependencies: + hardhat: ^2.0.0 + checksum: 870e7cad5d96ad7288b64da0faec7962a9a18e1eaaa02ed474e4f9285cd4b1a0fc6f66326e6a7476f7063fdf99aee57f227084519b1fb3723700a2d65fc65cfa + languageName: node + linkType: hard + "hardhat-deploy-ethers@npm:^0.3.0-beta.13": version: 0.3.0-beta.13 resolution: "hardhat-deploy-ethers@npm:0.3.0-beta.13" @@ -6520,6 +6887,39 @@ __metadata: languageName: node linkType: hard +"hardhat-deploy@npm:^0.10.5": + version: 0.10.6 + resolution: "hardhat-deploy@npm:0.10.6" + dependencies: + "@ethersproject/abi": ^5.4.0 + "@ethersproject/abstract-signer": ^5.4.1 + "@ethersproject/address": ^5.4.0 + "@ethersproject/bignumber": ^5.4.1 + "@ethersproject/bytes": ^5.4.0 + "@ethersproject/constants": ^5.4.0 + "@ethersproject/contracts": ^5.4.1 + "@ethersproject/providers": ^5.4.4 + "@ethersproject/solidity": ^5.4.0 + "@ethersproject/transactions": ^5.4.0 + "@ethersproject/wallet": ^5.4.0 + "@types/qs": ^6.9.7 + axios: ^0.21.1 + chalk: ^4.1.2 + chokidar: ^3.5.2 + debug: ^4.3.2 + enquirer: ^2.3.6 + form-data: ^4.0.0 + fs-extra: ^10.0.0 + match-all: ^1.2.6 + murmur-128: ^0.2.1 + qs: ^6.9.4 + peerDependencies: + "@ethersproject/hardware-wallets": ^5.0.14 + hardhat: ^2.6.8 + checksum: dd82fafd74da7f7d180c529ea7a044b8c9c9c0d65d5e05285bafeeb3f864492ffb2271174bc2ac4ed963d60f4bc3e95e4b70e4e063ee23807f34fbf6a29a8681 + languageName: node + linkType: hard + "hardhat-deploy@npm:^0.11.14, hardhat-deploy@npm:^0.11.26": version: 0.11.44 resolution: "hardhat-deploy@npm:0.11.44" @@ -6552,6 +6952,19 @@ __metadata: languageName: node linkType: hard +"hardhat-gas-reporter@npm:^1.0.6": + version: 1.0.10 + resolution: "hardhat-gas-reporter@npm:1.0.10" + dependencies: + array-uniq: 1.0.3 + eth-gas-reporter: ^0.2.25 + sha1: ^1.1.1 + peerDependencies: + hardhat: ^2.0.2 + checksum: caaec13ab3fcda47b8768257e4416b5fd0e8ef3aca5369aa8195419d3d4a948cc182075333651df44215cfc629d088f5ed9f762c8c14ae5a4b4a4f2613e583d0 + languageName: node + linkType: hard + "hardhat-gas-reporter@npm:^1.0.8": version: 1.0.9 resolution: "hardhat-gas-reporter@npm:1.0.9" @@ -6631,6 +7044,74 @@ __metadata: languageName: node linkType: hard +"hardhat@npm:^2.8.0": + version: 2.20.1 + resolution: "hardhat@npm:2.20.1" + dependencies: + "@ethersproject/abi": ^5.1.2 + "@metamask/eth-sig-util": ^4.0.0 + "@nomicfoundation/ethereumjs-block": 5.0.4 + "@nomicfoundation/ethereumjs-blockchain": 7.0.4 + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-evm": 2.0.4 + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-statemanager": 2.0.4 + "@nomicfoundation/ethereumjs-trie": 6.0.4 + "@nomicfoundation/ethereumjs-tx": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + "@nomicfoundation/ethereumjs-verkle": 0.0.2 + "@nomicfoundation/ethereumjs-vm": 7.0.4 + "@nomicfoundation/solidity-analyzer": ^0.1.0 + "@sentry/node": ^5.18.1 + "@types/bn.js": ^5.1.0 + "@types/lru-cache": ^5.1.0 + adm-zip: ^0.4.16 + aggregate-error: ^3.0.0 + ansi-escapes: ^4.3.0 + boxen: ^5.1.2 + chalk: ^2.4.2 + chokidar: ^3.4.0 + ci-info: ^2.0.0 + debug: ^4.1.1 + enquirer: ^2.3.0 + env-paths: ^2.2.0 + ethereum-cryptography: ^1.0.3 + ethereumjs-abi: ^0.6.8 + find-up: ^2.1.0 + fp-ts: 1.19.3 + fs-extra: ^7.0.1 + glob: 7.2.0 + immutable: ^4.0.0-rc.12 + io-ts: 1.10.4 + keccak: ^3.0.2 + lodash: ^4.17.11 + mnemonist: ^0.38.0 + mocha: ^10.0.0 + p-map: ^4.0.0 + raw-body: ^2.4.1 + resolve: 1.17.0 + semver: ^6.3.0 + solc: 0.7.3 + source-map-support: ^0.5.13 + stacktrace-parser: ^0.1.10 + tsort: 0.0.1 + undici: ^5.14.0 + uuid: ^8.3.2 + ws: ^7.4.6 + peerDependencies: + ts-node: "*" + typescript: "*" + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + bin: + hardhat: internal/cli/bootstrap.js + checksum: 191f2878f18740a59afa9afa3486487a6e2c7c57d54410779349a40a1046117b6329a151f6e66bba0c2a94b15f9880f38a1e4d7053c33eca022a3de5669326e8 + languageName: node + linkType: hard + "has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": version: 1.0.2 resolution: "has-bigints@npm:1.0.2" @@ -8097,6 +8578,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^10.0.0": + version: 10.2.0 + resolution: "lru-cache@npm:10.2.0" + checksum: eee7ddda4a7475deac51ac81d7dd78709095c6fa46e8350dc2d22462559a1faa3b81ed931d5464b13d48cbd7e08b46100b6f768c76833912bc444b99c37e25db + languageName: node + linkType: hard + "lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": version: 10.1.0 resolution: "lru-cache@npm:10.1.0" @@ -10326,6 +10814,22 @@ __metadata: languageName: node linkType: hard +"rust-verkle-wasm@npm:^0.0.1": + version: 0.0.1 + resolution: "rust-verkle-wasm@npm:0.0.1" + checksum: 24258e935d50b69d25d25d958ba4515b01470458ed7c42466cbc657104e826173827b838501eea1b94c71fd6c01fccd04829f0cc85cbad5d5c5d968c6d6df59e + languageName: node + linkType: hard + +"rustbn-wasm@npm:^0.2.0": + version: 0.2.0 + resolution: "rustbn-wasm@npm:0.2.0" + dependencies: + "@scure/base": ^1.1.1 + checksum: 9cf89ce88a9d161bce8ea2516b3037fe97e1debb2e9b86d6f3cd133e2c120c844644d37c61c27ae00475e49595a397e61559431875a61c5c52a04c40ba658872 + languageName: node + linkType: hard + "rustbn.js@npm:~0.2.0": version: 0.2.0 resolution: "rustbn.js@npm:0.2.0" @@ -11000,7 +11504,7 @@ __metadata: languageName: node linkType: hard -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3": +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -12063,6 +12567,15 @@ __metadata: languageName: node linkType: hard +"widest-line@npm:^3.1.0": + version: 3.1.0 + resolution: "widest-line@npm:3.1.0" + dependencies: + string-width: ^4.0.0 + checksum: 03db6c9d0af9329c37d74378ff1d91972b12553c7d72a6f4e8525fe61563fa7adb0b9d6e8d546b7e059688712ea874edd5ded475999abdeedf708de9849310e0 + languageName: node + linkType: hard + "word-wrap@npm:~1.2.3": version: 1.2.5 resolution: "word-wrap@npm:1.2.5" From 84d13e4b709451d22948748c02c95d977d69b68c Mon Sep 17 00:00:00 2001 From: chechu Date: Thu, 29 Feb 2024 10:23:04 +0000 Subject: [PATCH 43/53] feat: updating deployment files --- deployments/opbnbmainnet.json | 2049 +++++++++++++++++++++++ deployments/opbnbmainnet_addresses.json | 10 + deployments/opbnbtestnet.json | 2039 ++++++++++++++++++++++ deployments/opbnbtestnet_addresses.json | 10 + 4 files changed, 4108 insertions(+) create mode 100644 deployments/opbnbmainnet.json create mode 100644 deployments/opbnbmainnet_addresses.json create mode 100644 deployments/opbnbtestnet.json create mode 100644 deployments/opbnbtestnet_addresses.json diff --git a/deployments/opbnbmainnet.json b/deployments/opbnbmainnet.json new file mode 100644 index 00000000..e00ff059 --- /dev/null +++ b/deployments/opbnbmainnet.json @@ -0,0 +1,2049 @@ +{ + "name": "opbnbmainnet", + "chainId": "204", + "contracts": { + "DefaultProxyAdmin": { + "address": "0xF77bD1D893F67b3EB2Cd256239c98Ba3F238fb52", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ] + }, + "ProtocolShareReserve": { + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "percent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "oldPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPoolRegistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" + } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" + } + ], + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolRegistry", + "type": "address" + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ] + }, + "ProtocolShareReserve_Implementation": { + "address": "0xdA1675801de412da298Dc380CA530E1BeDe02fd0", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_corePoolComptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "_wbnb", + "type": "address" + }, + { + "internalType": "address", + "name": "_vbnb", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "percent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "oldPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPoolRegistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" + } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" + } + ], + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolRegistry", + "type": "address" + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "ProtocolShareReserve_Proxy": { + "address": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + } + } +} diff --git a/deployments/opbnbmainnet_addresses.json b/deployments/opbnbmainnet_addresses.json new file mode 100644 index 00000000..bc16846e --- /dev/null +++ b/deployments/opbnbmainnet_addresses.json @@ -0,0 +1,10 @@ +{ + "name": "opbnbmainnet", + "chainId": "204", + "addresses": { + "DefaultProxyAdmin": "0xF77bD1D893F67b3EB2Cd256239c98Ba3F238fb52", + "ProtocolShareReserve": "0xA2EDD515B75aBD009161B15909C19959484B0C1e", + "ProtocolShareReserve_Implementation": "0xdA1675801de412da298Dc380CA530E1BeDe02fd0", + "ProtocolShareReserve_Proxy": "0xA2EDD515B75aBD009161B15909C19959484B0C1e" + } +} diff --git a/deployments/opbnbtestnet.json b/deployments/opbnbtestnet.json new file mode 100644 index 00000000..e302def2 --- /dev/null +++ b/deployments/opbnbtestnet.json @@ -0,0 +1,2039 @@ +{ + "name": "opbnbtestnet", + "chainId": "5611", + "contracts": { + "DefaultProxyAdmin": { + "address": "0xB1281ADC816fba7df64B798D7A0BC4bd2a6d42f4", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ] + }, + "ProtocolShareReserve": { + "address": "0xc355dEb1A9289f8C58CFAa076EEdBf51F3A8Da7F", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "percent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "oldPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPoolRegistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" + } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" + } + ], + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolRegistry", + "type": "address" + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ] + }, + "ProtocolShareReserve_Implementation": { + "address": "0xD91a8d928413daEc12028800cb934562138b8b36", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_corePoolComptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "_wbnb", + "type": "address" + }, + { + "internalType": "address", + "name": "_vbnb", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "percent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "oldPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newPercentage", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPoolRegistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" + } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" + } + ], + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "percentage", + "type": "uint16" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + } + ], + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolRegistry", + "type": "address" + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "ProtocolShareReserve_Proxy": { + "address": "0xc355dEb1A9289f8C58CFAa076EEdBf51F3A8Da7F", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + } + } +} diff --git a/deployments/opbnbtestnet_addresses.json b/deployments/opbnbtestnet_addresses.json new file mode 100644 index 00000000..c29ba2d0 --- /dev/null +++ b/deployments/opbnbtestnet_addresses.json @@ -0,0 +1,10 @@ +{ + "name": "opbnbtestnet", + "chainId": "5611", + "addresses": { + "DefaultProxyAdmin": "0xB1281ADC816fba7df64B798D7A0BC4bd2a6d42f4", + "ProtocolShareReserve": "0xc355dEb1A9289f8C58CFAa076EEdBf51F3A8Da7F", + "ProtocolShareReserve_Implementation": "0xD91a8d928413daEc12028800cb934562138b8b36", + "ProtocolShareReserve_Proxy": "0xc355dEb1A9289f8C58CFAa076EEdBf51F3A8Da7F" + } +} From 4969d8e8673ac26a1802a3a2ba5fe17dbd4fbae1 Mon Sep 17 00:00:00 2001 From: Jesus Lanchas Date: Tue, 5 Mar 2024 15:33:14 +0100 Subject: [PATCH 44/53] fix: remove unneeded dependency --- hardhat.config.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 15789b3d..68280015 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -33,7 +33,6 @@ const externalDeployments = { "node_modules/@venusprotocol/isolated-pools/deployments/sepolia", ], opbnbtestnet: [ - "node_modules/@venusprotocol/venus-protocol/deployments/opbnbtestnet", "node_modules/@venusprotocol/governance-contracts/deployments/opbnbtestnet", "node_modules/@venusprotocol/oracle/deployments/opbnbtestnet", "node_modules/@venusprotocol/isolated-pools/deployments/opbnbtestnet", @@ -44,13 +43,11 @@ const externalDeployments = { "node_modules/@venusprotocol/isolated-pools/deployments/bscmainnet", ], ethereum: [ - "node_modules/@venusprotocol/venus-protocol/deployments/ethereum", "node_modules/@venusprotocol/governance-contracts/deployments/ethereum", "node_modules/@venusprotocol/oracle/deployments/ethereum", "node_modules/@venusprotocol/isolated-pools/deployments/ethereum", ], opbnbmainnet: [ - "node_modules/@venusprotocol/venus-protocol/deployments/opbnbmainnet", "node_modules/@venusprotocol/governance-contracts/deployments/opbnbmainnet", "node_modules/@venusprotocol/oracle/deployments/opbnbmainnet", "node_modules/@venusprotocol/isolated-pools/deployments/opbnbmainnet", From 7f355ddff366c22cbe166139843eb55c60d29867 Mon Sep 17 00:00:00 2001 From: 0xlucian <0xluciandev@gmail.com> Date: Tue, 5 Mar 2024 17:16:33 +0200 Subject: [PATCH 45/53] fix: CI --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 7fccb720..3bd501d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3328,7 +3328,7 @@ __metadata: languageName: unknown linkType: soft -"@venusprotocol/solidity-utilities@npm:1.3.0, @venusprotocol/solidity-utilities@npm:^1.3.0": +"@venusprotocol/solidity-utilities@npm:1.3.0, @venusprotocol/solidity-utilities@npm:^1.2.0, @venusprotocol/solidity-utilities@npm:^1.3.0": version: 1.3.0 resolution: "@venusprotocol/solidity-utilities@npm:1.3.0" checksum: d1109365a5e01959c47b25fb129373db93792e60bf1bc0ed324b63c2a64f6e4a7878ebf016cfade94bc41a2c1245d3e861fdc6b8c5844ac210ed1d73e7307e72 From 012adba98879077b3c4a940cf42c8e1e84fa2e06 Mon Sep 17 00:00:00 2001 From: 0xlucian <0xluciandev@gmail.com> Date: Wed, 6 Mar 2024 09:09:27 +0200 Subject: [PATCH 46/53] refactor: remove unused package --- package.json | 1 - yarn.lock | 543 +++------------------------------------------------ 2 files changed, 23 insertions(+), 521 deletions(-) diff --git a/package.json b/package.json index c8e5162d..832afc38 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "@typescript-eslint/parser": "^5.44.0", "@venusprotocol/governance-contracts": "^1.4.0", "@venusprotocol/oracle": "^1.10.0", - "@venusprotocol/venus-protocol": "^7.3.0", "bignumber.js": "^9.1.1", "chai": "^4.3.7", "dotenv": "^16.0.3", diff --git a/yarn.lock b/yarn.lock index 3bd501d7..7a4547d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -617,7 +617,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.0.9, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.4.0, @ethersproject/abi@npm:^5.6.3, @ethersproject/abi@npm:^5.7.0": +"@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.0.9, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.6.3, @ethersproject/abi@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abi@npm:5.7.0" dependencies: @@ -649,7 +649,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:5.7.0, @ethersproject/abstract-signer@npm:^5.4.1, @ethersproject/abstract-signer@npm:^5.7.0": +"@ethersproject/abstract-signer@npm:5.7.0, @ethersproject/abstract-signer@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abstract-signer@npm:5.7.0" dependencies: @@ -662,7 +662,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.4.0, @ethersproject/address@npm:^5.7.0": +"@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/address@npm:5.7.0" dependencies: @@ -694,7 +694,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.4.1, @ethersproject/bignumber@npm:^5.7.0": +"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bignumber@npm:5.7.0" dependencies: @@ -705,7 +705,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:^5.4.0, @ethersproject/bytes@npm:^5.7.0": +"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bytes@npm:5.7.0" dependencies: @@ -714,7 +714,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/constants@npm:5.7.0, @ethersproject/constants@npm:^5.4.0, @ethersproject/constants@npm:^5.7.0": +"@ethersproject/constants@npm:5.7.0, @ethersproject/constants@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/constants@npm:5.7.0" dependencies: @@ -723,7 +723,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/contracts@npm:5.7.0, @ethersproject/contracts@npm:^5.4.1, @ethersproject/contracts@npm:^5.7.0": +"@ethersproject/contracts@npm:5.7.0, @ethersproject/contracts@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/contracts@npm:5.7.0" dependencies: @@ -844,7 +844,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.4.4, @ethersproject/providers@npm:^5.7.0, @ethersproject/providers@npm:^5.7.1, @ethersproject/providers@npm:^5.7.2": +"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.7.0, @ethersproject/providers@npm:^5.7.1, @ethersproject/providers@npm:^5.7.2": version: 5.7.2 resolution: "@ethersproject/providers@npm:5.7.2" dependencies: @@ -917,7 +917,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/solidity@npm:5.7.0, @ethersproject/solidity@npm:^5.4.0, @ethersproject/solidity@npm:^5.7.0": +"@ethersproject/solidity@npm:5.7.0, @ethersproject/solidity@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/solidity@npm:5.7.0" dependencies: @@ -942,7 +942,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/transactions@npm:5.7.0, @ethersproject/transactions@npm:^5.4.0, @ethersproject/transactions@npm:^5.7.0": +"@ethersproject/transactions@npm:5.7.0, @ethersproject/transactions@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/transactions@npm:5.7.0" dependencies: @@ -970,7 +970,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/wallet@npm:5.7.0, @ethersproject/wallet@npm:^5.4.0, @ethersproject/wallet@npm:^5.7.0": +"@ethersproject/wallet@npm:5.7.0, @ethersproject/wallet@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/wallet@npm:5.7.0" dependencies: @@ -1131,36 +1131,6 @@ __metadata: languageName: node linkType: hard -"@layerzerolabs/lz-evm-sdk-v1-0.7@npm:^1.5.14": - version: 1.5.16 - resolution: "@layerzerolabs/lz-evm-sdk-v1-0.7@npm:1.5.16" - dependencies: - "@openzeppelin/contracts": 3.4.2-solc-0.7 - "@openzeppelin/contracts-upgradeable": 3.4.2-solc-0.7 - checksum: c4a42f446fe4c961bdfc5cbdd848b98ba1f2352ddd539d04affba7d9760905b0604a3422a1a9a7e89808466e6fcbb05e40498948b663beb21e47127b00d9cd9f - languageName: node - linkType: hard - -"@layerzerolabs/solidity-examples@npm:^1.0.0": - version: 1.1.0 - resolution: "@layerzerolabs/solidity-examples@npm:1.1.0" - dependencies: - "@layerzerolabs/lz-evm-sdk-v1-0.7": ^1.5.14 - "@openzeppelin-3/contracts": "npm:@openzeppelin/contracts@^3.4.2-solc-0.7" - "@openzeppelin/contracts": ^4.4.1 - "@openzeppelin/contracts-upgradeable": ^4.6.0 - "@openzeppelin/hardhat-upgrades": ^1.18.3 - dotenv: ^10.0.0 - erc721a: ^4.2.3 - hardhat: ^2.8.0 - hardhat-contract-sizer: ^2.1.1 - hardhat-deploy: ^0.10.5 - hardhat-deploy-ethers: ^0.3.0-beta.13 - hardhat-gas-reporter: ^1.0.6 - checksum: f7603710b18bdda227024b161059b5f725499529d25ea2c6dc7a16c664f2b25bd2be2761e81e870a08b05013c425bf7b5258e7a667ac9390cf598c043b216407 - languageName: node - linkType: hard - "@metamask/eth-sig-util@npm:^4.0.0": version: 4.0.1 resolution: "@metamask/eth-sig-util@npm:4.0.1" @@ -1267,20 +1237,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-block@npm:5.0.4": - version: 5.0.4 - resolution: "@nomicfoundation/ethereumjs-block@npm:5.0.4" - dependencies: - "@nomicfoundation/ethereumjs-common": 4.0.4 - "@nomicfoundation/ethereumjs-rlp": 5.0.4 - "@nomicfoundation/ethereumjs-trie": 6.0.4 - "@nomicfoundation/ethereumjs-tx": 5.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - ethereum-cryptography: 0.1.3 - checksum: fe60b3dc31e0991eb6659f838485384e52992b72dd97a42c7bec320ea9902d1200352b5690a222442f77c5447cee4dd834fc25c53247aed5aa3130b0ab7e3c53 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-blockchain@npm:6.2.2": version: 6.2.2 resolution: "@nomicfoundation/ethereumjs-blockchain@npm:6.2.2" @@ -1322,24 +1278,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-blockchain@npm:7.0.4": - version: 7.0.4 - resolution: "@nomicfoundation/ethereumjs-blockchain@npm:7.0.4" - dependencies: - "@nomicfoundation/ethereumjs-block": 5.0.4 - "@nomicfoundation/ethereumjs-common": 4.0.4 - "@nomicfoundation/ethereumjs-ethash": 3.0.4 - "@nomicfoundation/ethereumjs-rlp": 5.0.4 - "@nomicfoundation/ethereumjs-trie": 6.0.4 - "@nomicfoundation/ethereumjs-tx": 5.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - lru-cache: ^10.0.0 - checksum: 0d35f28ed5ef356557b974b91898b6f61292a3e0fd3d1b1c8924250a59c7f583939453184f5b54f7cd2a2d8c055cdc6f3b8588c7b22f839beaa4ba69638ba2c8 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-common@npm:3.1.2": version: 3.1.2 resolution: "@nomicfoundation/ethereumjs-common@npm:3.1.2" @@ -1360,15 +1298,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-common@npm:4.0.4": - version: 4.0.4 - resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.4" - dependencies: - "@nomicfoundation/ethereumjs-util": 9.0.4 - checksum: ce3f6e4ae15b976efdb7ccda27e19aadb62b5ffee209f9503e68b4fd8633715d4d697c0cc10ccd35f5e4e977edd05100d0f214e28880ec64fff77341dc34fcdf - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-ethash@npm:2.0.5": version: 2.0.5 resolution: "@nomicfoundation/ethereumjs-ethash@npm:2.0.5" @@ -1397,19 +1326,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-ethash@npm:3.0.4": - version: 3.0.4 - resolution: "@nomicfoundation/ethereumjs-ethash@npm:3.0.4" - dependencies: - "@nomicfoundation/ethereumjs-block": 5.0.4 - "@nomicfoundation/ethereumjs-rlp": 5.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - bigint-crypto-utils: ^3.2.2 - ethereum-cryptography: 0.1.3 - checksum: 52c2b003078be233929ae8355e8d2e0949ac66f75312a47725790b87111293de4303750a446f10eec22f5ffd9a2accb3f17fff8e6a85c36b47786e25242dad66 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-evm@npm:1.3.2, @nomicfoundation/ethereumjs-evm@npm:^1.0.0-rc.3": version: 1.3.2 resolution: "@nomicfoundation/ethereumjs-evm@npm:1.3.2" @@ -1442,22 +1358,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-evm@npm:2.0.4": - version: 2.0.4 - resolution: "@nomicfoundation/ethereumjs-evm@npm:2.0.4" - dependencies: - "@nomicfoundation/ethereumjs-common": 4.0.4 - "@nomicfoundation/ethereumjs-statemanager": 2.0.4 - "@nomicfoundation/ethereumjs-tx": 5.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - "@types/debug": ^4.1.9 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - rustbn-wasm: ^0.2.0 - checksum: db25327f7bda067cd0726a1bc7937c1c0405602fbe692abaa804f44e4fe9d2dcce103d50a767c0f3dc3067b38c35f468e997789234d2a4aef0ad31a36ad6d916 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-rlp@npm:4.0.3": version: 4.0.3 resolution: "@nomicfoundation/ethereumjs-rlp@npm:4.0.3" @@ -1476,15 +1376,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-rlp@npm:5.0.4": - version: 5.0.4 - resolution: "@nomicfoundation/ethereumjs-rlp@npm:5.0.4" - bin: - rlp: bin/rlp.cjs - checksum: ee2c2e5776c73801dc5ed636f4988b599b4563c2d0037da542ea57eb237c69dd1ac555f6bcb5e06f70515b6459779ba0d68252a6e105132b4659ab4bf62919b0 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-statemanager@npm:1.0.5": version: 1.0.5 resolution: "@nomicfoundation/ethereumjs-statemanager@npm:1.0.5" @@ -1514,27 +1405,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-statemanager@npm:2.0.4": - version: 2.0.4 - resolution: "@nomicfoundation/ethereumjs-statemanager@npm:2.0.4" - dependencies: - "@nomicfoundation/ethereumjs-common": 4.0.4 - "@nomicfoundation/ethereumjs-rlp": 5.0.4 - "@nomicfoundation/ethereumjs-trie": 6.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - js-sdsl: ^4.1.4 - lru-cache: ^10.0.0 - peerDependencies: - "@nomicfoundation/ethereumjs-verkle": 0.0.2 - peerDependenciesMeta: - "@nomicfoundation/ethereumjs-verkle": - optional: true - checksum: 585dc67872d37f39310d85fc5c1b3179691412b9450411422ad6468017d8723e5192d22447c927d8403f7b6e95c1ecf7b48467edc440e50f15b5ac81e1fecd1d - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-trie@npm:5.0.5": version: 5.0.5 resolution: "@nomicfoundation/ethereumjs-trie@npm:5.0.5" @@ -1560,20 +1430,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-trie@npm:6.0.4": - version: 6.0.4 - resolution: "@nomicfoundation/ethereumjs-trie@npm:6.0.4" - dependencies: - "@nomicfoundation/ethereumjs-rlp": 5.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - "@types/readable-stream": ^2.3.13 - ethereum-cryptography: 0.1.3 - lru-cache: ^10.0.0 - readable-stream: ^3.6.0 - checksum: 93a6be32657e67e74714fe557dbaf606d92c5cd1571c60f249295c27b0ab24b64e2e59cf211c214f8ba403d6475d23ed8c557be9077b92b2317e44384de8a6bf - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-tx@npm:4.1.2": version: 4.1.2 resolution: "@nomicfoundation/ethereumjs-tx@npm:4.1.2" @@ -1600,23 +1456,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-tx@npm:5.0.4": - version: 5.0.4 - resolution: "@nomicfoundation/ethereumjs-tx@npm:5.0.4" - dependencies: - "@nomicfoundation/ethereumjs-common": 4.0.4 - "@nomicfoundation/ethereumjs-rlp": 5.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - ethereum-cryptography: 0.1.3 - peerDependencies: - c-kzg: ^2.1.2 - peerDependenciesMeta: - c-kzg: - optional: true - checksum: 0f1c87716682ccbcf4d92ffc6cf8ab557e658b90319d82be3219a091a736859f8803c73c98e4863682e3e86d264751c472d33ff6d3c3daf4e75b5f01d0af8fa3 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-util@npm:8.0.6, @nomicfoundation/ethereumjs-util@npm:^8.0.0-rc.3": version: 8.0.6 resolution: "@nomicfoundation/ethereumjs-util@npm:8.0.6" @@ -1638,33 +1477,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-util@npm:9.0.4": - version: 9.0.4 - resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.4" - dependencies: - "@nomicfoundation/ethereumjs-rlp": 5.0.4 - ethereum-cryptography: 0.1.3 - peerDependencies: - c-kzg: ^2.1.2 - peerDependenciesMeta: - c-kzg: - optional: true - checksum: 754439f72b11cad2d8986707ad020077dcc763c4055f73e2668a0b4cadb22aa4407faa9b3c587d9eb5b97ac337afbe037eb642bc1d5a16197284f83db3462cbe - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-verkle@npm:0.0.2": - version: 0.0.2 - resolution: "@nomicfoundation/ethereumjs-verkle@npm:0.0.2" - dependencies: - "@nomicfoundation/ethereumjs-rlp": 5.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - lru-cache: ^10.0.0 - rust-verkle-wasm: ^0.0.1 - checksum: e075d7a2475670bb7039e715f0edce849ef3947aae2c7d0b658f058686ac9df3863499a5324717beff5d8f20a751f85ba1449942af818ec6772d775dcbb011d6 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-vm@npm:7.0.2": version: 7.0.2 resolution: "@nomicfoundation/ethereumjs-vm@npm:7.0.2" @@ -1686,25 +1498,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-vm@npm:7.0.4": - version: 7.0.4 - resolution: "@nomicfoundation/ethereumjs-vm@npm:7.0.4" - dependencies: - "@nomicfoundation/ethereumjs-block": 5.0.4 - "@nomicfoundation/ethereumjs-blockchain": 7.0.4 - "@nomicfoundation/ethereumjs-common": 4.0.4 - "@nomicfoundation/ethereumjs-evm": 2.0.4 - "@nomicfoundation/ethereumjs-rlp": 5.0.4 - "@nomicfoundation/ethereumjs-statemanager": 2.0.4 - "@nomicfoundation/ethereumjs-trie": 6.0.4 - "@nomicfoundation/ethereumjs-tx": 5.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - checksum: 6f3b2507189b236e65dd3eaf3f072385a0252b826a348fe6ea5532a810bc2b6aab11d8ccec2cdfed629995e61e4c82c6e8765ac5794154772064ba3f18397407 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-vm@npm:^6.0.0-rc.3": version: 6.4.2 resolution: "@nomicfoundation/ethereumjs-vm@npm:6.4.2" @@ -2282,27 +2075,6 @@ __metadata: languageName: node linkType: hard -"@openzeppelin-3/contracts@npm:@openzeppelin/contracts@^3.4.2-solc-0.7, @openzeppelin/contracts-v0.7@npm:@openzeppelin/contracts@v3.4.2": - version: 3.4.2 - resolution: "@openzeppelin/contracts@npm:3.4.2" - checksum: 0c90f029fe50a49643588e4c8670dae3bbf31795133a6ddce9bdcbc258486332700bb732287baabf7bf807f39182fe8ea2ffa19aa5caf359b1b9c0f083280748 - languageName: node - linkType: hard - -"@openzeppelin/contracts-upgradeable@npm:3.4.2-solc-0.7": - version: 3.4.2-solc-0.7 - resolution: "@openzeppelin/contracts-upgradeable@npm:3.4.2-solc-0.7" - checksum: 662d168ea1763faa5e168751043e4e041ccd810c3d4c781aa5aee0e9947e9f95d51edaeb1daaa4cc2860463beb961b576c6a3e60e3fbb6fa27188a611c8522e4 - languageName: node - linkType: hard - -"@openzeppelin/contracts-upgradeable@npm:^4.6.0": - version: 4.9.5 - resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.5" - checksum: d5d9bad93fe2a88a8336060901d45f185ebfe1fed9844b1fe50e8641d946588c6e69a5a8f1694f0bd073c913b4b9a5c34316acfc17d8f75228adecbcb635ea62 - languageName: node - linkType: hard - "@openzeppelin/contracts-upgradeable@npm:^4.7.3, @openzeppelin/contracts-upgradeable@npm:^4.8.0, @openzeppelin/contracts-upgradeable@npm:^4.8.3": version: 4.9.3 resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.3" @@ -2310,10 +2082,10 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/contracts@npm:3.4.2-solc-0.7": - version: 3.4.2-solc-0.7 - resolution: "@openzeppelin/contracts@npm:3.4.2-solc-0.7" - checksum: 1a6048f31ed560c34429a05e534102c51124ecaf113aca7ebeb7897cfaaf61007cdd7952374c282adaeb79b04ee86ee80b16eed28b62fc6d60e3ffcd7a696895 +"@openzeppelin/contracts-v0.7@npm:@openzeppelin/contracts@v3.4.2": + version: 3.4.2 + resolution: "@openzeppelin/contracts@npm:3.4.2" + checksum: 0c90f029fe50a49643588e4c8670dae3bbf31795133a6ddce9bdcbc258486332700bb732287baabf7bf807f39182fe8ea2ffa19aa5caf359b1b9c0f083280748 languageName: node linkType: hard @@ -2324,13 +2096,6 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/contracts@npm:^4.4.1": - version: 4.9.5 - resolution: "@openzeppelin/contracts@npm:4.9.5" - checksum: 2cddeb08c006a8f99c5cc40cc80aecb449fd941cd1a92ebda315d77f48c4b4d487798a1254bffbc3ec811b390365d14665e92dbb2dd8f45aacef479d69d94574 - languageName: node - linkType: hard - "@openzeppelin/defender-base-client@npm:^1.46.0": version: 1.52.0 resolution: "@openzeppelin/defender-base-client@npm:1.52.0" @@ -2344,7 +2109,7 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/hardhat-upgrades@npm:^1.18.3, @openzeppelin/hardhat-upgrades@npm:^1.21.0": +"@openzeppelin/hardhat-upgrades@npm:^1.21.0": version: 1.28.0 resolution: "@openzeppelin/hardhat-upgrades@npm:1.28.0" dependencies: @@ -2433,13 +2198,6 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:^1.1.1": - version: 1.1.5 - resolution: "@scure/base@npm:1.1.5" - checksum: 9e9ee6088cb3aa0fb91f5a48497d26682c7829df3019b1251d088d166d7a8c0f941c68aaa8e7b96bbad20c71eb210397cb1099062cde3e29d4bad6b975c18519 - languageName: node - linkType: hard - "@scure/base@npm:~1.1.0": version: 1.1.3 resolution: "@scure/base@npm:1.1.3" @@ -2870,15 +2628,6 @@ __metadata: languageName: node linkType: hard -"@types/debug@npm:^4.1.9": - version: 4.1.12 - resolution: "@types/debug@npm:4.1.12" - dependencies: - "@types/ms": "*" - checksum: 47876a852de8240bfdaf7481357af2b88cb660d30c72e73789abf00c499d6bc7cd5e52f41c915d1b9cd8ec9fef5b05688d7b7aef17f7f272c2d04679508d1053 - languageName: node - linkType: hard - "@types/events@npm:*": version: 3.0.3 resolution: "@types/events@npm:3.0.3" @@ -2947,13 +2696,6 @@ __metadata: languageName: node linkType: hard -"@types/ms@npm:*": - version: 0.7.34 - resolution: "@types/ms@npm:0.7.34" - checksum: f38d36e7b6edecd9badc9cf50474159e9da5fa6965a75186cceaf883278611b9df6669dc3a3cc122b7938d317b68a9e3d573d316fcb35d1be47ec9e468c6bd8a - languageName: node - linkType: hard - "@types/node@npm:*": version: 20.10.0 resolution: "@types/node@npm:20.10.0" @@ -3211,7 +2953,7 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/isolated-pools@npm:^2.5.0, @venusprotocol/isolated-pools@npm:^2.6.0": +"@venusprotocol/isolated-pools@npm:^2.6.0": version: 2.6.0 resolution: "@venusprotocol/isolated-pools@npm:2.6.0" dependencies: @@ -3248,7 +2990,7 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/protocol-reserve@npm:^1.1.0, @venusprotocol/protocol-reserve@npm:^1.4.0": +"@venusprotocol/protocol-reserve@npm:^1.1.0": version: 1.4.0 resolution: "@venusprotocol/protocol-reserve@npm:1.4.0" dependencies: @@ -3297,7 +3039,6 @@ __metadata: "@venusprotocol/isolated-pools": ^2.6.0 "@venusprotocol/oracle": ^1.10.0 "@venusprotocol/solidity-utilities": ^1.3.0 - "@venusprotocol/venus-protocol": ^7.3.0 bignumber.js: ^9.1.1 chai: ^4.3.7 dotenv: ^16.0.3 @@ -3328,7 +3069,7 @@ __metadata: languageName: unknown linkType: soft -"@venusprotocol/solidity-utilities@npm:1.3.0, @venusprotocol/solidity-utilities@npm:^1.2.0, @venusprotocol/solidity-utilities@npm:^1.3.0": +"@venusprotocol/solidity-utilities@npm:1.3.0, @venusprotocol/solidity-utilities@npm:^1.3.0": version: 1.3.0 resolution: "@venusprotocol/solidity-utilities@npm:1.3.0" checksum: d1109365a5e01959c47b25fb129373db93792e60bf1bc0ed324b63c2a64f6e4a7878ebf016cfade94bc41a2c1245d3e861fdc6b8c5844ac210ed1d73e7307e72 @@ -3342,21 +3083,6 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/token-bridge@npm:1.0.0": - version: 1.0.0 - resolution: "@venusprotocol/token-bridge@npm:1.0.0" - dependencies: - "@layerzerolabs/solidity-examples": ^1.0.0 - "@openzeppelin/contracts": ^4.8.3 - "@openzeppelin/contracts-upgradeable": ^4.8.3 - "@openzeppelin/hardhat-upgrades": ^1.21.0 - "@solidity-parser/parser": ^0.13.2 - ethers: ^5.7.0 - module-alias: ^2.2.2 - checksum: fa494157cc2493bcb4b2824fd545f2093b459404a449da6710c3c62ebd2638abc42cd15a06f60a7d537eb30e7e2efeab90961e34a60ecfef5d9c33c8e26b9405 - languageName: node - linkType: hard - "@venusprotocol/venus-protocol@npm:^6.0.0": version: 6.0.0 resolution: "@venusprotocol/venus-protocol@npm:6.0.0" @@ -3372,24 +3098,6 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/venus-protocol@npm:^7.3.0": - version: 7.3.0 - resolution: "@venusprotocol/venus-protocol@npm:7.3.0" - dependencies: - "@openzeppelin/contracts": 4.9.3 - "@openzeppelin/contracts-upgradeable": ^4.8.0 - "@venusprotocol/governance-contracts": ^1.4.0 - "@venusprotocol/isolated-pools": ^2.5.0 - "@venusprotocol/protocol-reserve": ^1.4.0 - "@venusprotocol/solidity-utilities": ^1.2.0 - "@venusprotocol/token-bridge": 1.0.0 - bignumber.js: ^9.1.2 - dotenv: ^16.0.1 - module-alias: ^2.2.2 - checksum: 2f277fca454a839471a7ddb09d5725e5eef2d974076acbeca461bff7209c041e9f39fdbcc1fd49832b77f2539ae83c438e6fdddb3a267552bcb4a08fbaa2bd92 - languageName: node - linkType: hard - "JSONStream@npm:^1.0.4, JSONStream@npm:^1.3.5": version: 1.3.5 resolution: "JSONStream@npm:1.3.5" @@ -3565,15 +3273,6 @@ __metadata: languageName: node linkType: hard -"ansi-align@npm:^3.0.0": - version: 3.0.1 - resolution: "ansi-align@npm:3.0.1" - dependencies: - string-width: ^4.1.0 - checksum: 6abfa08f2141d231c257162b15292467081fa49a208593e055c866aa0455b57f3a86b5a678c190c618faa79b4c59e254493099cb700dd9cf2293c6be2c8f5d8d - languageName: node - linkType: hard - "ansi-colors@npm:4.1.1": version: 4.1.1 resolution: "ansi-colors@npm:4.1.1" @@ -4020,7 +3719,7 @@ __metadata: languageName: node linkType: hard -"bigint-crypto-utils@npm:^3.0.23, bigint-crypto-utils@npm:^3.2.2": +"bigint-crypto-utils@npm:^3.0.23": version: 3.3.0 resolution: "bigint-crypto-utils@npm:3.3.0" checksum: 9598ce57b23f776c8936d44114c9f051e62b5fa654915b664784cbcbacc5aa0485f4479571c51ff58008abb1210c0d6a234853742f07cf84bda890f2a1e01000 @@ -4090,22 +3789,6 @@ __metadata: languageName: node linkType: hard -"boxen@npm:^5.1.2": - version: 5.1.2 - resolution: "boxen@npm:5.1.2" - dependencies: - ansi-align: ^3.0.0 - camelcase: ^6.2.0 - chalk: ^4.1.0 - cli-boxes: ^2.2.1 - string-width: ^4.2.2 - type-fest: ^0.20.2 - widest-line: ^3.1.0 - wrap-ansi: ^7.0.0 - checksum: 82d03e42a72576ff235123f17b7c505372fe05c83f75f61e7d4fa4bcb393897ec95ce766fecb8f26b915f0f7a7227d66e5ec7cef43f5b2bd9d3aeed47ec55877 - languageName: node - linkType: hard - "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -4348,7 +4031,7 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^6.0.0, camelcase@npm:^6.2.0": +"camelcase@npm:^6.0.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" checksum: 8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d @@ -4549,13 +4232,6 @@ __metadata: languageName: node linkType: hard -"cli-boxes@npm:^2.2.1": - version: 2.2.1 - resolution: "cli-boxes@npm:2.2.1" - checksum: be79f8ec23a558b49e01311b39a1ea01243ecee30539c880cf14bf518a12e223ef40c57ead0cb44f509bffdffc5c129c746cd50d863ab879385370112af4f585 - languageName: node - linkType: hard - "cli-columns@npm:^4.0.0": version: 4.0.0 resolution: "cli-columns@npm:4.0.0" @@ -4580,7 +4256,7 @@ __metadata: languageName: node linkType: hard -"cli-table3@npm:^0.6.0, cli-table3@npm:^0.6.2, cli-table3@npm:^0.6.3": +"cli-table3@npm:^0.6.2, cli-table3@npm:^0.6.3": version: 0.6.3 resolution: "cli-table3@npm:0.6.3" dependencies: @@ -5324,13 +5000,6 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^10.0.0": - version: 10.0.0 - resolution: "dotenv@npm:10.0.0" - checksum: f412c5fe8c24fbe313d302d2500e247ba8a1946492db405a4de4d30dd0eb186a88a43f13c958c5a7de303938949c4231c56994f97d05c4bc1f22478d631b4005 - languageName: node - linkType: hard - "dotenv@npm:^16.0.1, dotenv@npm:^16.0.3": version: 16.3.1 resolution: "dotenv@npm:16.3.1" @@ -5427,13 +5096,6 @@ __metadata: languageName: node linkType: hard -"erc721a@npm:^4.2.3": - version: 4.2.3 - resolution: "erc721a@npm:4.2.3" - checksum: 0b2223678219d9b4a228da880cca9aab396ebe9cb59baf34a5501d4d9d297024d492ee5335c1983cd4c3bd15deef5e162c4837d27ac5ab5bf66e01591ead425c - languageName: node - linkType: hard - "err-code@npm:^2.0.2": version: 2.0.3 resolution: "err-code@npm:2.0.3" @@ -6864,19 +6526,6 @@ __metadata: languageName: node linkType: hard -"hardhat-contract-sizer@npm:^2.1.1": - version: 2.10.0 - resolution: "hardhat-contract-sizer@npm:2.10.0" - dependencies: - chalk: ^4.0.0 - cli-table3: ^0.6.0 - strip-ansi: ^6.0.0 - peerDependencies: - hardhat: ^2.0.0 - checksum: 870e7cad5d96ad7288b64da0faec7962a9a18e1eaaa02ed474e4f9285cd4b1a0fc6f66326e6a7476f7063fdf99aee57f227084519b1fb3723700a2d65fc65cfa - languageName: node - linkType: hard - "hardhat-deploy-ethers@npm:^0.3.0-beta.13": version: 0.3.0-beta.13 resolution: "hardhat-deploy-ethers@npm:0.3.0-beta.13" @@ -6887,39 +6536,6 @@ __metadata: languageName: node linkType: hard -"hardhat-deploy@npm:^0.10.5": - version: 0.10.6 - resolution: "hardhat-deploy@npm:0.10.6" - dependencies: - "@ethersproject/abi": ^5.4.0 - "@ethersproject/abstract-signer": ^5.4.1 - "@ethersproject/address": ^5.4.0 - "@ethersproject/bignumber": ^5.4.1 - "@ethersproject/bytes": ^5.4.0 - "@ethersproject/constants": ^5.4.0 - "@ethersproject/contracts": ^5.4.1 - "@ethersproject/providers": ^5.4.4 - "@ethersproject/solidity": ^5.4.0 - "@ethersproject/transactions": ^5.4.0 - "@ethersproject/wallet": ^5.4.0 - "@types/qs": ^6.9.7 - axios: ^0.21.1 - chalk: ^4.1.2 - chokidar: ^3.5.2 - debug: ^4.3.2 - enquirer: ^2.3.6 - form-data: ^4.0.0 - fs-extra: ^10.0.0 - match-all: ^1.2.6 - murmur-128: ^0.2.1 - qs: ^6.9.4 - peerDependencies: - "@ethersproject/hardware-wallets": ^5.0.14 - hardhat: ^2.6.8 - checksum: dd82fafd74da7f7d180c529ea7a044b8c9c9c0d65d5e05285bafeeb3f864492ffb2271174bc2ac4ed963d60f4bc3e95e4b70e4e063ee23807f34fbf6a29a8681 - languageName: node - linkType: hard - "hardhat-deploy@npm:^0.11.14, hardhat-deploy@npm:^0.11.26": version: 0.11.44 resolution: "hardhat-deploy@npm:0.11.44" @@ -6952,19 +6568,6 @@ __metadata: languageName: node linkType: hard -"hardhat-gas-reporter@npm:^1.0.6": - version: 1.0.10 - resolution: "hardhat-gas-reporter@npm:1.0.10" - dependencies: - array-uniq: 1.0.3 - eth-gas-reporter: ^0.2.25 - sha1: ^1.1.1 - peerDependencies: - hardhat: ^2.0.2 - checksum: caaec13ab3fcda47b8768257e4416b5fd0e8ef3aca5369aa8195419d3d4a948cc182075333651df44215cfc629d088f5ed9f762c8c14ae5a4b4a4f2613e583d0 - languageName: node - linkType: hard - "hardhat-gas-reporter@npm:^1.0.8": version: 1.0.9 resolution: "hardhat-gas-reporter@npm:1.0.9" @@ -7044,74 +6647,6 @@ __metadata: languageName: node linkType: hard -"hardhat@npm:^2.8.0": - version: 2.20.1 - resolution: "hardhat@npm:2.20.1" - dependencies: - "@ethersproject/abi": ^5.1.2 - "@metamask/eth-sig-util": ^4.0.0 - "@nomicfoundation/ethereumjs-block": 5.0.4 - "@nomicfoundation/ethereumjs-blockchain": 7.0.4 - "@nomicfoundation/ethereumjs-common": 4.0.4 - "@nomicfoundation/ethereumjs-evm": 2.0.4 - "@nomicfoundation/ethereumjs-rlp": 5.0.4 - "@nomicfoundation/ethereumjs-statemanager": 2.0.4 - "@nomicfoundation/ethereumjs-trie": 6.0.4 - "@nomicfoundation/ethereumjs-tx": 5.0.4 - "@nomicfoundation/ethereumjs-util": 9.0.4 - "@nomicfoundation/ethereumjs-verkle": 0.0.2 - "@nomicfoundation/ethereumjs-vm": 7.0.4 - "@nomicfoundation/solidity-analyzer": ^0.1.0 - "@sentry/node": ^5.18.1 - "@types/bn.js": ^5.1.0 - "@types/lru-cache": ^5.1.0 - adm-zip: ^0.4.16 - aggregate-error: ^3.0.0 - ansi-escapes: ^4.3.0 - boxen: ^5.1.2 - chalk: ^2.4.2 - chokidar: ^3.4.0 - ci-info: ^2.0.0 - debug: ^4.1.1 - enquirer: ^2.3.0 - env-paths: ^2.2.0 - ethereum-cryptography: ^1.0.3 - ethereumjs-abi: ^0.6.8 - find-up: ^2.1.0 - fp-ts: 1.19.3 - fs-extra: ^7.0.1 - glob: 7.2.0 - immutable: ^4.0.0-rc.12 - io-ts: 1.10.4 - keccak: ^3.0.2 - lodash: ^4.17.11 - mnemonist: ^0.38.0 - mocha: ^10.0.0 - p-map: ^4.0.0 - raw-body: ^2.4.1 - resolve: 1.17.0 - semver: ^6.3.0 - solc: 0.7.3 - source-map-support: ^0.5.13 - stacktrace-parser: ^0.1.10 - tsort: 0.0.1 - undici: ^5.14.0 - uuid: ^8.3.2 - ws: ^7.4.6 - peerDependencies: - ts-node: "*" - typescript: "*" - peerDependenciesMeta: - ts-node: - optional: true - typescript: - optional: true - bin: - hardhat: internal/cli/bootstrap.js - checksum: 191f2878f18740a59afa9afa3486487a6e2c7c57d54410779349a40a1046117b6329a151f6e66bba0c2a94b15f9880f38a1e4d7053c33eca022a3de5669326e8 - languageName: node - linkType: hard - "has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": version: 1.0.2 resolution: "has-bigints@npm:1.0.2" @@ -8578,13 +8113,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.0": - version: 10.2.0 - resolution: "lru-cache@npm:10.2.0" - checksum: eee7ddda4a7475deac51ac81d7dd78709095c6fa46e8350dc2d22462559a1faa3b81ed931d5464b13d48cbd7e08b46100b6f768c76833912bc444b99c37e25db - languageName: node - linkType: hard - "lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": version: 10.1.0 resolution: "lru-cache@npm:10.1.0" @@ -10814,22 +10342,6 @@ __metadata: languageName: node linkType: hard -"rust-verkle-wasm@npm:^0.0.1": - version: 0.0.1 - resolution: "rust-verkle-wasm@npm:0.0.1" - checksum: 24258e935d50b69d25d25d958ba4515b01470458ed7c42466cbc657104e826173827b838501eea1b94c71fd6c01fccd04829f0cc85cbad5d5c5d968c6d6df59e - languageName: node - linkType: hard - -"rustbn-wasm@npm:^0.2.0": - version: 0.2.0 - resolution: "rustbn-wasm@npm:0.2.0" - dependencies: - "@scure/base": ^1.1.1 - checksum: 9cf89ce88a9d161bce8ea2516b3037fe97e1debb2e9b86d6f3cd133e2c120c844644d37c61c27ae00475e49595a397e61559431875a61c5c52a04c40ba658872 - languageName: node - linkType: hard - "rustbn.js@npm:~0.2.0": version: 0.2.0 resolution: "rustbn.js@npm:0.2.0" @@ -11504,7 +11016,7 @@ __metadata: languageName: node linkType: hard -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3": +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -12567,15 +12079,6 @@ __metadata: languageName: node linkType: hard -"widest-line@npm:^3.1.0": - version: 3.1.0 - resolution: "widest-line@npm:3.1.0" - dependencies: - string-width: ^4.0.0 - checksum: 03db6c9d0af9329c37d74378ff1d91972b12553c7d72a6f4e8525fe61563fa7adb0b9d6e8d546b7e059688712ea874edd5ded475999abdeedf708de9849310e0 - languageName: node - linkType: hard - "word-wrap@npm:~1.2.3": version: 1.2.5 resolution: "word-wrap@npm:1.2.5" From ff827ef162aff981e3d68a94bce43088126c4098 Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Thu, 14 Mar 2024 07:52:45 +0000 Subject: [PATCH 47/53] chore(release): 1.5.0-dev.6 [skip ci] ## [1.5.0-dev.6](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.5...v1.5.0-dev.6) (2024-03-14) ### Features * updating deployment files ([84d13e4](https://github.com/VenusProtocol/protocol-reserve/commit/84d13e4b709451d22948748c02c95d977d69b68c)) * upgrade dependencies and export opbnbmainnet addresses ([eab12a8](https://github.com/VenusProtocol/protocol-reserve/commit/eab12a84929160b7bf7994347f81b68bfa078d96)) ### Bug Fixes * CI ([7f355dd](https://github.com/VenusProtocol/protocol-reserve/commit/7f355ddff366c22cbe166139843eb55c60d29867)) * remove unneeded dependency ([4969d8e](https://github.com/VenusProtocol/protocol-reserve/commit/4969d8e8673ac26a1802a3a2ba5fe17dbd4fbae1)) --- CHANGELOG.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36d081c6..51343b8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## [1.5.0-dev.6](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.5...v1.5.0-dev.6) (2024-03-14) + + +### Features + +* updating deployment files ([84d13e4](https://github.com/VenusProtocol/protocol-reserve/commit/84d13e4b709451d22948748c02c95d977d69b68c)) +* upgrade dependencies and export opbnbmainnet addresses ([eab12a8](https://github.com/VenusProtocol/protocol-reserve/commit/eab12a84929160b7bf7994347f81b68bfa078d96)) + + +### Bug Fixes + +* CI ([7f355dd](https://github.com/VenusProtocol/protocol-reserve/commit/7f355ddff366c22cbe166139843eb55c60d29867)) +* remove unneeded dependency ([4969d8e](https://github.com/VenusProtocol/protocol-reserve/commit/4969d8e8673ac26a1802a3a2ba5fe17dbd4fbae1)) + ## [1.5.0-dev.5](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.4...v1.5.0-dev.5) (2024-03-05) diff --git a/package.json b/package.json index 832afc38..ff31603e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@venusprotocol/protocol-reserve", "description": "Venus Protocol contracts to manage the income generated by the protocol", - "version": "1.5.0-dev.5", + "version": "1.5.0-dev.6", "author": "Venus", "engines": { "node": ">=18.0.0" From e16ffed42d92837c1a4351a21291651046a3fb02 Mon Sep 17 00:00:00 2001 From: 0xlucian <0xluciandev@gmail.com> Date: Thu, 14 Mar 2024 10:54:12 +0200 Subject: [PATCH 48/53] refactor: RiskFund deployment script and migrate deployments from IL --- deploy/006-risk-fund-v2.ts | 33 +- deployments/bscmainnet/RiskFundV2.json | 728 ++++------- .../bscmainnet/RiskFundV2_Implementation.json | 1113 +++++++++++++++++ deployments/bscmainnet/RiskFundV2_Proxy.json | 277 ++++ deployments/bsctestnet/RiskFundV2.json | 758 +++++------ .../bsctestnet/RiskFundV2_Implementation.json | 1049 ++++++++++++++++ deployments/bsctestnet/RiskFundV2_Proxy.json | 277 ++++ 7 files changed, 3314 insertions(+), 921 deletions(-) create mode 100644 deployments/bscmainnet/RiskFundV2_Implementation.json create mode 100644 deployments/bscmainnet/RiskFundV2_Proxy.json create mode 100644 deployments/bsctestnet/RiskFundV2_Implementation.json create mode 100644 deployments/bsctestnet/RiskFundV2_Proxy.json diff --git a/deploy/006-risk-fund-v2.ts b/deploy/006-risk-fund-v2.ts index 229994de..e081db94 100644 --- a/deploy/006-risk-fund-v2.ts +++ b/deploy/006-risk-fund-v2.ts @@ -1,15 +1,40 @@ +import { ethers } from "hardhat"; +import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async ({ getNamedAccounts, deployments }: HardhatRuntimeEnvironment) => { +import { multisigs } from "../helpers/utils"; + +const func: DeployFunction = async ({ + network: { name }, + getNamedAccounts, + deployments, +}: HardhatRuntimeEnvironment) => { const { deploy } = deployments; const { deployer } = await getNamedAccounts(); + + const proxyAdmin = await ethers.getContract("DefaultProxyAdmin"); + const owner = await proxyAdmin.owner(); + await deploy("RiskFundV2", { - contract: "RiskFundV2", from: deployer, - args: [], - log: true, + contract: "RiskFundV2", + proxy: { + owner: owner, + proxyContract: "OpenZeppelinTransparentProxy", + upgradeIndex: 0, + }, autoMine: true, + log: true, }); + + const targetOwner = (await ethers.getContractOrNull("NormalTimelock"))?.address || multisigs[name]; + + const contract = await ethers.getContract("RiskFundV2"); + if ((await contract.owner()) !== targetOwner && (await contract.pendingOwner()) !== targetOwner) { + console.log(`Transferring ownership of RiskFundV2 to ${targetOwner}`); + const tx = await contract.transferOwnership(targetOwner); + await tx.wait(); + } }; func.tags = ["RiskFundV2"]; diff --git a/deployments/bscmainnet/RiskFundV2.json b/deployments/bscmainnet/RiskFundV2.json index 1d134775..73e307fa 100644 --- a/deployments/bscmainnet/RiskFundV2.json +++ b/deployments/bscmainnet/RiskFundV2.json @@ -1,6 +1,150 @@ { - "address": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, { "inputs": [], "name": "InsufficientBalance", @@ -621,493 +765,143 @@ "type": "function" } ], - "transactionHash": "0x7d93e90484be2ae340f2d9eb4389ebdbd012eb0f0161cf5a5c8b98c1a8a237e4", + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", "receipt": { "to": null, - "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", - "transactionIndex": 42, - "gasUsed": "1417978", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xa2f1b69e987fa3f01fdf9be5ad673c9e4370c6c9396a9786b1d5178d8c4587bb", - "transactionHash": "0x7d93e90484be2ae340f2d9eb4389ebdbd012eb0f0161cf5a5c8b98c1a8a237e4", - "logs": [], - "blockNumber": 35547098, - "cumulativeGasUsed": "5087006", + "from": "0x55A9f5374Af30E3045FB491f1da3C2E8a74d168D", + "contractAddress": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "transactionIndex": 49, + "gasUsed": "888558", + "logsBloom": "0x00000000010000000000000000000000400000000000000000800000000000000000000000000000000000000000000000200000000000000000000000008000000000000000000000000000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000000000020000000400000000080000000000000800000000000000000000000002000000400000000000000800000000000000000000000000020000020000000000001040000400000000400000000000000001020000000000200000000000000000000000000000800000000000400000000020000", + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67", + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "logs": [ + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x00000000000000000000000087ac8dd81ec00d2183a04d22884e7fc67f6ce0c8" + ], + "data": "0x", + "logIndex": 87, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + }, + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000055a9f5374af30e3045fb491f1da3c2e8a74d168d" + ], + "data": "0x", + "logIndex": 88, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + }, + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 89, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + }, + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 90, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + }, + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 91, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + }, + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006beb6d2695b67feb73ad4f172e8e2975497187e4", + "logIndex": 92, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + } + ], + "blockNumber": 31670886, + "cumulativeGasUsed": "5316071", "status": 1, "byzantium": true }, - "args": [], - "numDeployments": 2, - "solcInputHash": "e599bc05495d18590ac88167d546a0ef", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"poolReserve\",\"type\":\"uint256\"}],\"name\":\"InsufficientPoolReserve\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRiskFundConverter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortfallAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsDecreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldRiskFundConverter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newRiskFundConverter\",\"type\":\"address\"}],\"name\":\"RiskFundConverterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newShortfallContract\",\"type\":\"address\"}],\"name\":\"ShortfallContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepTokenFromPool\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLoopsLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolAssetsFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"riskFundConverter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"riskFundConverter_\",\"type\":\"address\"}],\"name\":\"setRiskFundConverter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepTokenFromPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"updatePoolState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"details\":\"This contract does not support BNB\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"custom:event\":\"ConvertibleBaseAssetUpdated emit on success\",\"details\":\"Convertible base asset setter\",\"params\":{\"convertibleBaseAsset_\":\"Address of the convertible base asset\"}},\"setRiskFundConverter(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when risk fund converter address is zero\",\"custom:event\":\"RiskFundConverterUpdated emit on success\",\"details\":\"Risk fund converter setter\",\"params\":{\"riskFundConverter_\":\"Address of the risk fund converter\"}},\"setShortfallContractAddress(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"custom:event\":\"ShortfallContractUpdated emit on success\",\"details\":\"Shortfall contract address setter\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zeroZeroValueNotAllowed is thrown when amount is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"Amount need to sweep for the pool\",\"to\":\"Address to which assets will be transferred\",\"tokenAddress\":\"Address of the asset(token)\"}},\"sweepTokenFromPool(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zeroZeroValueNotAllowed is thrown when amount is zero\",\"custom:event\":\"Emits sweepTokenFromPool event on success\",\"params\":{\"amount\":\"Amount need to sweep from the pool\",\"comptroller\":\"Pool address to which assets will be transferred\",\"tokenAddress\":\"Address of the asset(token)\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"transferReserveForAuction(address,uint256)\":{\"custom:access\":\"Only Shortfall contract\",\"custom:error\":\"InvalidShortfallAddress is thrown when caller is not shortfall contractInsufficientPoolReserve is thrown when pool reserve is less than the amount needed\",\"custom:event\":\"TransferredReserveForAuction emit on success\",\"details\":\"Transfer tokens for auction to shortfall contract\",\"params\":{\"amount\":\"Amount to be transferred to the shortfall\",\"comptroller\":\"Comptroller of the pool\"},\"returns\":{\"_0\":\"Amount of tokens transferred to the shortfall\"}},\"updatePoolState(address,address,uint256)\":{\"custom:access\":\"Only RiskFundConverter contract\",\"custom:error\":\"InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\",\"custom:event\":\"PoolAssetsIncreased emits on success\",\"details\":\"Update the reserve of the asset for the specific pool after transferring to risk fund\",\"params\":{\"amount\":\"Amount transferred for the pool\",\"asset\":\"Address of the asset(token)\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"RiskFundV2\",\"version\":1},\"userdoc\":{\"errors\":{\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientPoolReserve(address,uint256,uint256)\":[{\"notice\":\"Error is thrown when pool reserve is less than the amount needed\"}],\"InvalidRiskFundConverter()\":[{\"notice\":\"Error is thrown when updatePoolState is not called by riskFundConverter\"}],\"InvalidShortfallAddress()\":[{\"notice\":\"Error is thrown when transferReserveForAuction is called by non shortfall address\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset address is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDecreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\"},\"PoolAssetsIncreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred to this contract\"},\"RiskFundConverterUpdated(address,address)\":{\"notice\":\"Emitted when risk fund converter address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"},\"SweepTokenFromPool(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept and transferred from pool\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"convertibleBaseAsset()\":{\"notice\":\"Address of base asset\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"maxLoopsLimit()\":{\"notice\":\"Limit for the loops to avoid the DOSThis state is deprecated, using it to prevent storage collision\"},\"poolAssetsFunds(address,address)\":{\"notice\":\"Available asset's fund per pool in RiskFund Comptroller(pool) -> Asset -> amount\"},\"riskFundConverter()\":{\"notice\":\"Risk fund converter address\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"shortfall()\":{\"notice\":\"Address of shortfall contract\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"Function to sweep baseAsset for pool, Tokens are sent to address(to)\"},\"sweepTokenFromPool(address,address,uint256)\":{\"notice\":\"Function to sweep token from pool\"}},\"notice\":\"Contract with basic features to hold base asset for different Comptrollers\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ProtocolReserve/RiskFundV2.sol\":\"RiskFundV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IRiskFundConverter {\\n function updateAssetsState(address comptroller, address asset) external;\\n\\n function getPools(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb7335d0d343100ca6294c5858193f52462d1818212ff4435c14da961af87a39e\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\n\\n/// @title ReserveHelpersStorage\\n/// @author Venus\\n/// @dev Reserve helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract ReserveHelpersStorage is Ownable2StepUpgradeable {\\n /// @notice Deprecated slot for assetReserves mapping\\n bytes32 private __deprecatedSlot1;\\n\\n /// @notice Available asset's fund per pool in RiskFund\\n /// Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) public poolAssetsFunds;\\n\\n /// @notice Deprecated slot for poolRegistry address\\n bytes32 private __deprecatedSlot2;\\n /// @notice Deprecated slot for status variable\\n bytes32 private __deprecatedSlot3;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n uint256[46] private __gap;\\n}\\n\\n/// @title MaxLoopsLimitHelpersStorage\\n/// @author Venus\\n/// @dev Max loop limit helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract MaxLoopsLimitHelpersStorage {\\n /// @notice Limit for the loops to avoid the DOS\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 public maxLoopsLimit;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[49] private __gap;\\n}\\n\\n/// @title RiskFundV1Storage\\n/// @author Venus\\n/// @dev Risk fund V1 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV1Storage is ReserveHelpersStorage, MaxLoopsLimitHelpersStorage {\\n /// @notice Address of base asset\\n address public convertibleBaseAsset;\\n /// @notice Address of shortfall contract\\n address public shortfall;\\n\\n /// @notice This state is deprecated, using it to prevent storage collision\\n address private pancakeSwapRouter;\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 private minAmountToConvert;\\n}\\n\\n/// @title RiskFundV2Storage\\n/// @author Venus\\n/// @dev Risk fund V2 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeable {\\n /// @notice Risk fund converter address\\n address public riskFundConverter;\\n}\\n\",\"keccak256\":\"0x0620187dca927191ab256ea20e42416883380690e54ba344807867adba01d7fb\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { IRiskFund } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IRiskFundConverter } from \\\"../Interfaces/IRiskFundConverter.sol\\\";\\nimport { RiskFundV2Storage } from \\\"./RiskFundStorage.sol\\\";\\n\\n/// @title RiskFundV2\\n/// @author Venus\\n/// @notice Contract with basic features to hold base asset for different Comptrollers\\n/// @dev This contract does not support BNB\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Emitted when convertible base asset address is updated\\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\\n\\n /// @notice Emitted when risk fund converter address is updated\\n event RiskFundConverterUpdated(address indexed oldRiskFundConverter, address indexed newRiskFundConverter);\\n\\n /// @notice Emitted when shortfall contract address is updated\\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\\n\\n /// @notice Emitted when reserves are transferred for auction\\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred to this contract\\n event PoolAssetsIncreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\\n event PoolAssetsDecreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Event emitted when tokens are swept and transferred from pool\\n event SweepTokenFromPool(address indexed token, address indexed comptroller, uint256 amount);\\n\\n /// @notice Error is thrown when updatePoolState is not called by riskFundConverter\\n error InvalidRiskFundConverter();\\n\\n /// @notice Error is thrown when transferReserveForAuction is called by non shortfall address\\n error InvalidShortfallAddress();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice Error is thrown when pool reserve is less than the amount needed\\n error InsufficientPoolReserve(address comptroller, uint256 amount, uint256 poolReserve);\\n\\n /// @dev Convertible base asset setter\\n /// @param convertibleBaseAsset_ Address of the convertible base asset\\n /// @custom:event ConvertibleBaseAssetUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\\n /// @custom:access Only Governance\\n function setConvertibleBaseAsset(address convertibleBaseAsset_) external onlyOwner {\\n ensureNonzeroAddress(convertibleBaseAsset_);\\n emit ConvertibleBaseAssetUpdated(convertibleBaseAsset, convertibleBaseAsset_);\\n convertibleBaseAsset = convertibleBaseAsset_;\\n }\\n\\n /// @dev Risk fund converter setter\\n /// @param riskFundConverter_ Address of the risk fund converter\\n /// @custom:event RiskFundConverterUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when risk fund converter address is zero\\n /// @custom:access Only Governance\\n function setRiskFundConverter(address riskFundConverter_) external onlyOwner {\\n ensureNonzeroAddress(riskFundConverter_);\\n emit RiskFundConverterUpdated(riskFundConverter, riskFundConverter_);\\n riskFundConverter = riskFundConverter_;\\n }\\n\\n /// @dev Shortfall contract address setter\\n /// @param shortfallContractAddress_ Address of the auction contract\\n /// @custom:event ShortfallContractUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n /// @custom:access Only Governance\\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\\n ensureNonzeroAddress(shortfallContractAddress_);\\n emit ShortfallContractUpdated(shortfall, shortfallContractAddress_);\\n shortfall = shortfallContractAddress_;\\n }\\n\\n /// @dev Transfer tokens for auction to shortfall contract\\n /// @param comptroller Comptroller of the pool\\n /// @param amount Amount to be transferred to the shortfall\\n /// @return Amount of tokens transferred to the shortfall\\n /// @custom:event TransferredReserveForAuction emit on success\\n /// @custom:error InvalidShortfallAddress is thrown when caller is not shortfall contract\\n /// @custom:error InsufficientPoolReserve is thrown when pool reserve is less than the amount needed\\n /// @custom:access Only Shortfall contract\\n function transferReserveForAuction(address comptroller, uint256 amount)\\n external\\n override\\n nonReentrant\\n returns (uint256)\\n {\\n uint256 poolReserve = poolAssetsFunds[comptroller][convertibleBaseAsset];\\n\\n if (msg.sender != shortfall) {\\n revert InvalidShortfallAddress();\\n }\\n if (amount > poolReserve) {\\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\\n }\\n\\n unchecked {\\n poolAssetsFunds[comptroller][convertibleBaseAsset] = poolReserve - amount;\\n }\\n\\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall, amount);\\n emit TransferredReserveForAuction(comptroller, amount);\\n\\n return amount;\\n }\\n\\n /// @notice Function to sweep baseAsset for pool, Tokens are sent to address(to)\\n /// @param tokenAddress Address of the asset(token)\\n /// @param to Address to which assets will be transferred\\n /// @param amount Amount need to sweep for the pool\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice Function to sweep token from pool\\n /// @param tokenAddress Address of the asset(token)\\n /// @param comptroller Pool address to which assets will be transferred\\n /// @param amount Amount need to sweep from the pool\\n /// @custom:event Emits sweepTokenFromPool event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zero\\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\\n /// @custom:access Only Governance\\n function sweepTokenFromPool(\\n address tokenAddress,\\n address comptroller,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(comptroller);\\n ensureNonzeroValue(amount);\\n\\n uint256 poolReserve = poolAssetsFunds[comptroller][tokenAddress];\\n\\n if (amount > poolReserve) {\\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\\n }\\n\\n unchecked {\\n poolAssetsFunds[comptroller][tokenAddress] = poolReserve - amount;\\n }\\n\\n IERC20Upgradeable(tokenAddress).safeTransfer(comptroller, amount);\\n\\n emit SweepTokenFromPool(tokenAddress, comptroller, amount);\\n }\\n\\n /**\\n * @notice Get the Amount of the Base asset in the risk fund for the specific pool.\\n * @param comptroller Comptroller address(pool).\\n * @return Base Asset's reserve in risk fund.\\n */\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256) {\\n return poolAssetsFunds[comptroller][convertibleBaseAsset];\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Address of the asset(token)\\n /// @param amount Amount transferred for the pool\\n /// @custom:event PoolAssetsIncreased emits on success\\n /// @custom:error InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\\n /// @custom:access Only RiskFundConverter contract\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) public {\\n if (msg.sender != riskFundConverter) {\\n revert InvalidRiskFundConverter();\\n }\\n\\n poolAssetsFunds[comptroller][asset] += amount;\\n emit PoolAssetsIncreased(comptroller, asset, amount);\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\\n function preSweepToken(address tokenAddress, uint256 amount) internal {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n\\n address[] memory pools = IRiskFundConverter(riskFundConverter).getPools(tokenAddress);\\n\\n uint256 assetReserves;\\n uint256 poolsLength = pools.length;\\n for (uint256 i; i < poolsLength; ) {\\n assetReserves += poolAssetsFunds[pools[i]][tokenAddress];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256 balanceDiff = balance - assetReserves;\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n uint256 distributedShare;\\n for (uint256 i; i < poolsLength; ) {\\n if (poolAssetsFunds[pools[i]][tokenAddress] != 0) {\\n uint256 poolAmountShare;\\n if (i < (poolsLength - 1)) {\\n poolAmountShare = (poolAssetsFunds[pools[i]][tokenAddress] * amount) / assetReserves;\\n distributedShare += poolAmountShare;\\n } else {\\n poolAmountShare = amountDiff - distributedShare;\\n }\\n poolAssetsFunds[pools[i]][tokenAddress] -= poolAmountShare;\\n emit PoolAssetsDecreased(pools[i], tokenAddress, poolAmountShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x311a4e348835634eaa4aaf08515f91552513cdf1f5a01c05bf75f939a294bf2e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506118db806100206000396000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c806377d4937f116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102ff578063e30c397814610313578063f2fde38b1461032457600080fd5b8063b4a0bdf3146102e5578063be26317e146102f657600080fd5b8063855a8dd2116100b2578063855a8dd2146102865780638da5cb5b14610299578063a69bd19e146102aa57600080fd5b806377d4937f1461026b57806379ba50971461027e57600080fd5b806353ac353711610124578063601bb5a911610109578063601bb5a91461023d57806364aff9ec14610250578063715018a61461026357600080fd5b806353ac3537146101ff5780635dbe35331461021257600080fd5b806319b1faef1161015557806319b1faef146101ac5780632e688141146101d85780632eef9172146101eb57600080fd5b80630a9837c5146101715780630e32cb8614610197575b600080fd5b61018461017f3660046114dc565b610337565b6040519081526020015b60405180910390f35b6101aa6101a5366004611508565b610496565b005b61012e546101c0906001600160a01b031681565b6040516001600160a01b03909116815260200161018e565b6101aa6101e6366004611508565b6104aa565b610163546101c0906001600160a01b031681565b6101aa61020d36600461152c565b610531565b61018461022036600461156d565b60ca60209081526000928352604080842090915290825290205481565b6101aa61024b366004611508565b610606565b6101aa61025e36600461152c565b61068d565b6101aa610735565b6101aa610279366004611508565b610749565b6101aa6107d0565b6101aa61029436600461152c565b610875565b6033546001600160a01b03166101c0565b6101846102b8366004611508565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101c0565b61018460fb5481565b61012d546101c0906001600160a01b031681565b6065546001600160a01b03166101c0565b6101aa610332366004611508565b610996565b6000610341610a1f565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e5490911633146103aa576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80831115610402576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461044692908116911685610a94565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161048191815260200190565b60405180910390a25050600161013155919050565b61049e610b14565b6104a781610b88565b50565b6104b2610b14565b6104bb81610c97565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610576576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca60209081526040808320938616835292905290812080548392906105ad9084906115d5565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105f991815260200190565b60405180910390a3505050565b61060e610b14565b61061781610c97565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610695610b14565b61069d610a1f565b6106a683610c97565b6106af82610c97565b6106b881610cd7565b826106c38183610d11565b6106d76001600160a01b0382168484610a94565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d58460405161071c91815260200190565b60405180910390a350610730600161013155565b505050565b61073d610b14565b6107476000611135565b565b610751610b14565b61075a81610c97565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461086c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103f9565b6104a781611135565b61087d610b14565b610885610a1f565b61088e83610c97565b61089782610c97565b6108a081610cd7565b6001600160a01b03808316600090815260ca602090815260408083209387168352929052205480821115610919576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260248101839052604481018290526064016103f9565b6001600160a01b03808416600090815260ca602090815260408083209388168084529390915290208383039055610951908484610a94565b826001600160a01b0316846001600160a01b03167f0e8a97dff226f3ada9da954f9bd38f73280b03ef851bfc7c97db1343f07bdbdc8460405161071c91815260200190565b61099e610b14565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556109e76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60026101315403610a8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103f9565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610730908490611166565b6033546001600160a01b03163314610747576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103f9565b6001600160a01b038116610c1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103f9565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b0381166104a7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000036104a7576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9591906115ed565b905080821115610dd1576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610e36573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610e7c9190810190611645565b8051909150600090815b81811015610f055760ca6000858381518110610ea457610ea4611728565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610efb91906115d5565b9250600101610e86565b506000610f128386611757565b90508581101561112c578086036000805b848110156111285760ca6000888381518110610f4157610f41611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014611120576000610fa1600187611757565b82101561103357868a60ca60008b8681518110610fc057610fc0611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054611016919061176e565b61102091906117ab565b905061102c81846115d5565b9250611040565b61103d8385611757565b90505b8060ca60008a858151811061105757611057611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546110b19190611757565b925050819055508a6001600160a01b03168883815181106110d4576110d4611728565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd843208360405161111691815260200190565b60405180910390a3505b600101610f23565b5050505b50505050505050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556104a781611268565b60006111bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166112d29092919063ffffffff16565b90508051600014806111dc5750808060200190518101906111dc91906117e6565b610730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103f9565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606112e184846000856112e9565b949350505050565b60608247101561137b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103f9565b600080866001600160a01b031685876040516113979190611838565b60006040518083038185875af1925050503d80600081146113d4576040519150601f19603f3d011682016040523d82523d6000602084013e6113d9565b606091505b50915091506113ea878383876113f5565b979650505050505050565b6060831561147e578251600003611477576001600160a01b0385163b611477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103f9565b50816112e1565b6112e183838151156114935781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f99190611854565b6001600160a01b03811681146104a757600080fd5b600080604083850312156114ef57600080fd5b82356114fa816114c7565b946020939093013593505050565b60006020828403121561151a57600080fd5b8135611525816114c7565b9392505050565b60008060006060848603121561154157600080fd5b833561154c816114c7565b9250602084013561155c816114c7565b929592945050506040919091013590565b6000806040838503121561158057600080fd5b823561158b816114c7565b9150602083013561159b816114c7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115e8576115e86115a6565b500190565b6000602082840312156115ff57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8051611640816114c7565b919050565b6000602080838503121561165857600080fd5b825167ffffffffffffffff8082111561167057600080fd5b818501915085601f83011261168457600080fd5b81518181111561169657611696611606565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811085821117156116d9576116d9611606565b6040529182528482019250838101850191888311156116f757600080fd5b938501935b8285101561171c5761170d85611635565b845293850193928501926116fc565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082821015611769576117696115a6565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156117a6576117a66115a6565b500290565b6000826117e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156117f857600080fd5b8151801515811461152557600080fd5b60005b8381101561182357818101518382015260200161180b565b83811115611832576000848401525b50505050565b6000825161184a818460208701611808565b9190910192915050565b6020815260008251806020840152611873816040850160208701611808565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220ae70b20469fe0d634614028f8d5ab4bd856fb444c39affcec03bff538f7033cd64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061016c5760003560e01c806377d4937f116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102ff578063e30c397814610313578063f2fde38b1461032457600080fd5b8063b4a0bdf3146102e5578063be26317e146102f657600080fd5b8063855a8dd2116100b2578063855a8dd2146102865780638da5cb5b14610299578063a69bd19e146102aa57600080fd5b806377d4937f1461026b57806379ba50971461027e57600080fd5b806353ac353711610124578063601bb5a911610109578063601bb5a91461023d57806364aff9ec14610250578063715018a61461026357600080fd5b806353ac3537146101ff5780635dbe35331461021257600080fd5b806319b1faef1161015557806319b1faef146101ac5780632e688141146101d85780632eef9172146101eb57600080fd5b80630a9837c5146101715780630e32cb8614610197575b600080fd5b61018461017f3660046114dc565b610337565b6040519081526020015b60405180910390f35b6101aa6101a5366004611508565b610496565b005b61012e546101c0906001600160a01b031681565b6040516001600160a01b03909116815260200161018e565b6101aa6101e6366004611508565b6104aa565b610163546101c0906001600160a01b031681565b6101aa61020d36600461152c565b610531565b61018461022036600461156d565b60ca60209081526000928352604080842090915290825290205481565b6101aa61024b366004611508565b610606565b6101aa61025e36600461152c565b61068d565b6101aa610735565b6101aa610279366004611508565b610749565b6101aa6107d0565b6101aa61029436600461152c565b610875565b6033546001600160a01b03166101c0565b6101846102b8366004611508565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101c0565b61018460fb5481565b61012d546101c0906001600160a01b031681565b6065546001600160a01b03166101c0565b6101aa610332366004611508565b610996565b6000610341610a1f565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e5490911633146103aa576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80831115610402576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461044692908116911685610a94565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161048191815260200190565b60405180910390a25050600161013155919050565b61049e610b14565b6104a781610b88565b50565b6104b2610b14565b6104bb81610c97565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610576576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca60209081526040808320938616835292905290812080548392906105ad9084906115d5565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105f991815260200190565b60405180910390a3505050565b61060e610b14565b61061781610c97565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610695610b14565b61069d610a1f565b6106a683610c97565b6106af82610c97565b6106b881610cd7565b826106c38183610d11565b6106d76001600160a01b0382168484610a94565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d58460405161071c91815260200190565b60405180910390a350610730600161013155565b505050565b61073d610b14565b6107476000611135565b565b610751610b14565b61075a81610c97565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461086c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103f9565b6104a781611135565b61087d610b14565b610885610a1f565b61088e83610c97565b61089782610c97565b6108a081610cd7565b6001600160a01b03808316600090815260ca602090815260408083209387168352929052205480821115610919576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260248101839052604481018290526064016103f9565b6001600160a01b03808416600090815260ca602090815260408083209388168084529390915290208383039055610951908484610a94565b826001600160a01b0316846001600160a01b03167f0e8a97dff226f3ada9da954f9bd38f73280b03ef851bfc7c97db1343f07bdbdc8460405161071c91815260200190565b61099e610b14565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556109e76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60026101315403610a8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103f9565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610730908490611166565b6033546001600160a01b03163314610747576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103f9565b6001600160a01b038116610c1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103f9565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b0381166104a7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000036104a7576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9591906115ed565b905080821115610dd1576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610e36573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610e7c9190810190611645565b8051909150600090815b81811015610f055760ca6000858381518110610ea457610ea4611728565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610efb91906115d5565b9250600101610e86565b506000610f128386611757565b90508581101561112c578086036000805b848110156111285760ca6000888381518110610f4157610f41611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014611120576000610fa1600187611757565b82101561103357868a60ca60008b8681518110610fc057610fc0611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054611016919061176e565b61102091906117ab565b905061102c81846115d5565b9250611040565b61103d8385611757565b90505b8060ca60008a858151811061105757611057611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546110b19190611757565b925050819055508a6001600160a01b03168883815181106110d4576110d4611728565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd843208360405161111691815260200190565b60405180910390a3505b600101610f23565b5050505b50505050505050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556104a781611268565b60006111bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166112d29092919063ffffffff16565b90508051600014806111dc5750808060200190518101906111dc91906117e6565b610730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103f9565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606112e184846000856112e9565b949350505050565b60608247101561137b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103f9565b600080866001600160a01b031685876040516113979190611838565b60006040518083038185875af1925050503d80600081146113d4576040519150601f19603f3d011682016040523d82523d6000602084013e6113d9565b606091505b50915091506113ea878383876113f5565b979650505050505050565b6060831561147e578251600003611477576001600160a01b0385163b611477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103f9565b50816112e1565b6112e183838151156114935781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f99190611854565b6001600160a01b03811681146104a757600080fd5b600080604083850312156114ef57600080fd5b82356114fa816114c7565b946020939093013593505050565b60006020828403121561151a57600080fd5b8135611525816114c7565b9392505050565b60008060006060848603121561154157600080fd5b833561154c816114c7565b9250602084013561155c816114c7565b929592945050506040919091013590565b6000806040838503121561158057600080fd5b823561158b816114c7565b9150602083013561159b816114c7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115e8576115e86115a6565b500190565b6000602082840312156115ff57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8051611640816114c7565b919050565b6000602080838503121561165857600080fd5b825167ffffffffffffffff8082111561167057600080fd5b818501915085601f83011261168457600080fd5b81518181111561169657611696611606565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811085821117156116d9576116d9611606565b6040529182528482019250838101850191888311156116f757600080fd5b938501935b8285101561171c5761170d85611635565b845293850193928501926116fc565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082821015611769576117696115a6565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156117a6576117a66115a6565b500290565b6000826117e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156117f857600080fd5b8151801515811461152557600080fd5b60005b8381101561182357818101518382015260200161180b565b83811115611832576000848401525b50505050565b6000825161184a818460208701611808565b9190910192915050565b6020815260008251806020840152611873816040850160208701611808565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220ae70b20469fe0d634614028f8d5ab4bd856fb444c39affcec03bff538f7033cd64736f6c634300080d0033", + "args": [ + "0x87ac8dD81Ec00D2183a04D22884e7FC67f6ce0C8", + "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4", + "0x2a1d05470000000000000000000000008938e6da30b59c1e27d5f70a94688a89f7c815a40000000000000000000000000000000000000000000000008ac7230489e8000000000000000000000000000055d398326f99059ff775485246999027b31979550000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c235550000000000000000000000000000000000000000000000000000000000000064" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "execute": { + "methodName": "initialize", + "args": [ + "0x8938E6dA30b59c1E27d5f70a94688A89F7c815a4", + "10000000000000000000", + "0x55d398326f99059fF775485246999027B3197955", + "0x4788629ABc6cFCA10F9f969efdEAa1cF70c23555", + 100 + ] + }, + "implementation": "0x87ac8dD81Ec00D2183a04D22884e7FC67f6ce0C8", "devdoc": { - "author": "Venus", - "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", - "details": "This contract does not support BNB", + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", "kind": "dev", "methods": { - "acceptOwnership()": { - "details": "The new owner accepts the ownership transfer." - }, - "getPoolsBaseAssetReserves(address)": { - "params": { - "comptroller": "Comptroller address(pool)." - }, - "returns": { - "_0": "Base Asset's reserve in risk fund." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "pendingOwner()": { - "details": "Returns the address of the pending owner." + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." }, - "setAccessControlManager(address)": { - "custom:access": "Only Governance", - "custom:event": "Emits NewAccessControlManager event", - "details": "Admin function to set address of AccessControlManager", - "params": { - "accessControlManager_": "The new address of the AccessControlManager" - } - }, - "setConvertibleBaseAsset(address)": { - "custom:access": "Only Governance", - "custom:error": "ZeroAddressNotAllowed is thrown when convertible base asset address is zero", - "custom:event": "ConvertibleBaseAssetUpdated emit on success", - "details": "Convertible base asset setter", - "params": { - "convertibleBaseAsset_": "Address of the convertible base asset" - } - }, - "setRiskFundConverter(address)": { - "custom:access": "Only Governance", - "custom:error": "ZeroAddressNotAllowed is thrown when risk fund converter address is zero", - "custom:event": "RiskFundConverterUpdated emit on success", - "details": "Risk fund converter setter", - "params": { - "riskFundConverter_": "Address of the risk fund converter" - } + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." }, - "setShortfallContractAddress(address)": { - "custom:access": "Only Governance", - "custom:error": "ZeroAddressNotAllowed is thrown when shortfall contract address is zero", - "custom:event": "ShortfallContractUpdated emit on success", - "details": "Shortfall contract address setter", - "params": { - "shortfallContractAddress_": "Address of the auction contract" - } + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" }, - "sweepToken(address,address,uint256)": { - "custom:access": "Only Governance", - "custom:error": "ZeroAddressNotAllowed is thrown when tokenAddress/to address is zeroZeroValueNotAllowed is thrown when amount is zero", - "custom:event": "Emits SweepToken event on success", - "params": { - "amount": "Amount need to sweep for the pool", - "to": "Address to which assets will be transferred", - "tokenAddress": "Address of the asset(token)" - } + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." }, - "sweepTokenFromPool(address,address,uint256)": { - "custom:access": "Only Governance", - "custom:error": "ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zeroZeroValueNotAllowed is thrown when amount is zero", - "custom:event": "Emits sweepTokenFromPool event on success", - "params": { - "amount": "Amount need to sweep from the pool", - "comptroller": "Pool address to which assets will be transferred", - "tokenAddress": "Address of the asset(token)" - } - }, - "transferOwnership(address)": { - "details": "Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner." - }, - "transferReserveForAuction(address,uint256)": { - "custom:access": "Only Shortfall contract", - "custom:error": "InvalidShortfallAddress is thrown when caller is not shortfall contractInsufficientPoolReserve is thrown when pool reserve is less than the amount needed", - "custom:event": "TransferredReserveForAuction emit on success", - "details": "Transfer tokens for auction to shortfall contract", - "params": { - "amount": "Amount to be transferred to the shortfall", - "comptroller": "Comptroller of the pool" - }, - "returns": { - "_0": "Amount of tokens transferred to the shortfall" - } - }, - "updatePoolState(address,address,uint256)": { - "custom:access": "Only RiskFundConverter contract", - "custom:error": "InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract", - "custom:event": "PoolAssetsIncreased emits on success", - "details": "Update the reserve of the asset for the specific pool after transferring to risk fund", - "params": { - "amount": "Amount transferred for the pool", - "asset": "Address of the asset(token)", - "comptroller": "Comptroller address (pool)" - } + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." } }, - "title": "RiskFundV2", "version": 1 }, "userdoc": { - "errors": { - "InsufficientBalance()": [ - { - "notice": "thrown when amount entered is greater than balance" - } - ], - "InsufficientPoolReserve(address,uint256,uint256)": [ - { - "notice": "Error is thrown when pool reserve is less than the amount needed" - } - ], - "InvalidRiskFundConverter()": [ - { - "notice": "Error is thrown when updatePoolState is not called by riskFundConverter" - } - ], - "InvalidShortfallAddress()": [ - { - "notice": "Error is thrown when transferReserveForAuction is called by non shortfall address" - } - ], - "Unauthorized(address,address,string)": [ - { - "notice": "Thrown when the action is prohibited by AccessControlManager" - } - ], - "ZeroAddressNotAllowed()": [ - { - "notice": "Thrown if the supplied address is a zero address where it is not allowed" - } - ], - "ZeroValueNotAllowed()": [ - { - "notice": "Thrown if the supplied value is 0 where it is not allowed" - } - ] - }, - "events": { - "ConvertibleBaseAssetUpdated(address,address)": { - "notice": "Emitted when convertible base asset address is updated" - }, - "NewAccessControlManager(address,address)": { - "notice": "Emitted when access control manager contract address is changed" - }, - "PoolAssetsDecreased(address,address,uint256)": { - "notice": "Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens" - }, - "PoolAssetsIncreased(address,address,uint256)": { - "notice": "Emitted when pool asset states is updated with amount transferred to this contract" - }, - "RiskFundConverterUpdated(address,address)": { - "notice": "Emitted when risk fund converter address is updated" - }, - "ShortfallContractUpdated(address,address)": { - "notice": "Emitted when shortfall contract address is updated" - }, - "SweepToken(address,address,uint256)": { - "notice": "Event emitted when tokens are swept" - }, - "SweepTokenFromPool(address,address,uint256)": { - "notice": "Event emitted when tokens are swept and transferred from pool" - }, - "TransferredReserveForAuction(address,uint256)": { - "notice": "Emitted when reserves are transferred for auction" - } - }, "kind": "user", - "methods": { - "accessControlManager()": { - "notice": "Returns the address of the access control manager contract" - }, - "convertibleBaseAsset()": { - "notice": "Address of base asset" - }, - "getPoolsBaseAssetReserves(address)": { - "notice": "Get the Amount of the Base asset in the risk fund for the specific pool." - }, - "maxLoopsLimit()": { - "notice": "Limit for the loops to avoid the DOSThis state is deprecated, using it to prevent storage collision" - }, - "poolAssetsFunds(address,address)": { - "notice": "Available asset's fund per pool in RiskFund Comptroller(pool) -> Asset -> amount" - }, - "riskFundConverter()": { - "notice": "Risk fund converter address" - }, - "setAccessControlManager(address)": { - "notice": "Sets the address of AccessControlManager" - }, - "shortfall()": { - "notice": "Address of shortfall contract" - }, - "sweepToken(address,address,uint256)": { - "notice": "Function to sweep baseAsset for pool, Tokens are sent to address(to)" - }, - "sweepTokenFromPool(address,address,uint256)": { - "notice": "Function to sweep token from pool" - } - }, - "notice": "Contract with basic features to hold base asset for different Comptrollers", + "methods": {}, "version": 1 }, "storageLayout": { - "storage": [ - { - "astId": 244, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 247, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 1478, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 116, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 236, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 25, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_pendingOwner", - "offset": 0, - "slot": "101", - "type": "t_address" - }, - { - "astId": 104, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 4921, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_accessControlManager", - "offset": 0, - "slot": "151", - "type": "t_contract(IAccessControlManagerV8)5106" - }, - { - "astId": 4926, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 7563, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__deprecatedSlot1", - "offset": 0, - "slot": "201", - "type": "t_bytes32" - }, - { - "astId": 7570, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "poolAssetsFunds", - "offset": 0, - "slot": "202", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 7573, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__deprecatedSlot2", - "offset": 0, - "slot": "203", - "type": "t_bytes32" - }, - { - "astId": 7576, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__deprecatedSlot3", - "offset": 0, - "slot": "204", - "type": "t_bytes32" - }, - { - "astId": 7581, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "205", - "type": "t_array(t_uint256)46_storage" - }, - { - "astId": 7586, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "maxLoopsLimit", - "offset": 0, - "slot": "251", - "type": "t_uint256" - }, - { - "astId": 7591, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "252", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 7600, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "convertibleBaseAsset", - "offset": 0, - "slot": "301", - "type": "t_address" - }, - { - "astId": 7603, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "shortfall", - "offset": 0, - "slot": "302", - "type": "t_address" - }, - { - "astId": 7606, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "pancakeSwapRouter", - "offset": 0, - "slot": "303", - "type": "t_address" - }, - { - "astId": 7609, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "minAmountToConvert", - "offset": 0, - "slot": "304", - "type": "t_uint256" - }, - { - "astId": 547, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_status", - "offset": 0, - "slot": "305", - "type": "t_uint256" - }, - { - "astId": 616, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "306", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 7618, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "riskFundConverter", - "offset": 0, - "slot": "355", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)46_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[46]", - "numberOfBytes": "1472" - }, - "t_array(t_uint256)49_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(IAccessControlManagerV8)5106": { - "encoding": "inplace", - "label": "contract IAccessControlManagerV8", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } + "storage": [], + "types": null } } diff --git a/deployments/bscmainnet/RiskFundV2_Implementation.json b/deployments/bscmainnet/RiskFundV2_Implementation.json new file mode 100644 index 00000000..1d134775 --- /dev/null +++ b/deployments/bscmainnet/RiskFundV2_Implementation.json @@ -0,0 +1,1113 @@ +{ + "address": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", + "abi": [ + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "poolReserve", + "type": "uint256" + } + ], + "name": "InsufficientPoolReserve", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRiskFundConverter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortfallAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldConvertibleBaseAsset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newConvertibleBaseAsset", + "type": "address" + } + ], + "name": "ConvertibleBaseAssetUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "PoolAssetsDecreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "PoolAssetsIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldRiskFundConverter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newRiskFundConverter", + "type": "address" + } + ], + "name": "RiskFundConverterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldShortfallContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newShortfallContract", + "type": "address" + } + ], + "name": "ShortfallContractUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepTokenFromPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferredReserveForAuction", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "convertibleBaseAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolsBaseAssetReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "poolAssetsFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "riskFundConverter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "convertibleBaseAsset_", + "type": "address" + } + ], + "name": "setConvertibleBaseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "riskFundConverter_", + "type": "address" + } + ], + "name": "setRiskFundConverter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "shortfallContractAddress_", + "type": "address" + } + ], + "name": "setShortfallContractAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepTokenFromPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferReserveForAuction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "updatePoolState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x7d93e90484be2ae340f2d9eb4389ebdbd012eb0f0161cf5a5c8b98c1a8a237e4", + "receipt": { + "to": null, + "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", + "contractAddress": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", + "transactionIndex": 42, + "gasUsed": "1417978", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa2f1b69e987fa3f01fdf9be5ad673c9e4370c6c9396a9786b1d5178d8c4587bb", + "transactionHash": "0x7d93e90484be2ae340f2d9eb4389ebdbd012eb0f0161cf5a5c8b98c1a8a237e4", + "logs": [], + "blockNumber": 35547098, + "cumulativeGasUsed": "5087006", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 2, + "solcInputHash": "e599bc05495d18590ac88167d546a0ef", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"poolReserve\",\"type\":\"uint256\"}],\"name\":\"InsufficientPoolReserve\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRiskFundConverter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortfallAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsDecreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldRiskFundConverter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newRiskFundConverter\",\"type\":\"address\"}],\"name\":\"RiskFundConverterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newShortfallContract\",\"type\":\"address\"}],\"name\":\"ShortfallContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepTokenFromPool\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLoopsLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolAssetsFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"riskFundConverter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"riskFundConverter_\",\"type\":\"address\"}],\"name\":\"setRiskFundConverter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepTokenFromPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"updatePoolState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"details\":\"This contract does not support BNB\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"custom:event\":\"ConvertibleBaseAssetUpdated emit on success\",\"details\":\"Convertible base asset setter\",\"params\":{\"convertibleBaseAsset_\":\"Address of the convertible base asset\"}},\"setRiskFundConverter(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when risk fund converter address is zero\",\"custom:event\":\"RiskFundConverterUpdated emit on success\",\"details\":\"Risk fund converter setter\",\"params\":{\"riskFundConverter_\":\"Address of the risk fund converter\"}},\"setShortfallContractAddress(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"custom:event\":\"ShortfallContractUpdated emit on success\",\"details\":\"Shortfall contract address setter\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zeroZeroValueNotAllowed is thrown when amount is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"Amount need to sweep for the pool\",\"to\":\"Address to which assets will be transferred\",\"tokenAddress\":\"Address of the asset(token)\"}},\"sweepTokenFromPool(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zeroZeroValueNotAllowed is thrown when amount is zero\",\"custom:event\":\"Emits sweepTokenFromPool event on success\",\"params\":{\"amount\":\"Amount need to sweep from the pool\",\"comptroller\":\"Pool address to which assets will be transferred\",\"tokenAddress\":\"Address of the asset(token)\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"transferReserveForAuction(address,uint256)\":{\"custom:access\":\"Only Shortfall contract\",\"custom:error\":\"InvalidShortfallAddress is thrown when caller is not shortfall contractInsufficientPoolReserve is thrown when pool reserve is less than the amount needed\",\"custom:event\":\"TransferredReserveForAuction emit on success\",\"details\":\"Transfer tokens for auction to shortfall contract\",\"params\":{\"amount\":\"Amount to be transferred to the shortfall\",\"comptroller\":\"Comptroller of the pool\"},\"returns\":{\"_0\":\"Amount of tokens transferred to the shortfall\"}},\"updatePoolState(address,address,uint256)\":{\"custom:access\":\"Only RiskFundConverter contract\",\"custom:error\":\"InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\",\"custom:event\":\"PoolAssetsIncreased emits on success\",\"details\":\"Update the reserve of the asset for the specific pool after transferring to risk fund\",\"params\":{\"amount\":\"Amount transferred for the pool\",\"asset\":\"Address of the asset(token)\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"RiskFundV2\",\"version\":1},\"userdoc\":{\"errors\":{\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientPoolReserve(address,uint256,uint256)\":[{\"notice\":\"Error is thrown when pool reserve is less than the amount needed\"}],\"InvalidRiskFundConverter()\":[{\"notice\":\"Error is thrown when updatePoolState is not called by riskFundConverter\"}],\"InvalidShortfallAddress()\":[{\"notice\":\"Error is thrown when transferReserveForAuction is called by non shortfall address\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset address is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDecreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\"},\"PoolAssetsIncreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred to this contract\"},\"RiskFundConverterUpdated(address,address)\":{\"notice\":\"Emitted when risk fund converter address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"},\"SweepTokenFromPool(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept and transferred from pool\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"convertibleBaseAsset()\":{\"notice\":\"Address of base asset\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"maxLoopsLimit()\":{\"notice\":\"Limit for the loops to avoid the DOSThis state is deprecated, using it to prevent storage collision\"},\"poolAssetsFunds(address,address)\":{\"notice\":\"Available asset's fund per pool in RiskFund Comptroller(pool) -> Asset -> amount\"},\"riskFundConverter()\":{\"notice\":\"Risk fund converter address\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"shortfall()\":{\"notice\":\"Address of shortfall contract\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"Function to sweep baseAsset for pool, Tokens are sent to address(to)\"},\"sweepTokenFromPool(address,address,uint256)\":{\"notice\":\"Function to sweep token from pool\"}},\"notice\":\"Contract with basic features to hold base asset for different Comptrollers\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ProtocolReserve/RiskFundV2.sol\":\"RiskFundV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IRiskFundConverter {\\n function updateAssetsState(address comptroller, address asset) external;\\n\\n function getPools(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb7335d0d343100ca6294c5858193f52462d1818212ff4435c14da961af87a39e\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\n\\n/// @title ReserveHelpersStorage\\n/// @author Venus\\n/// @dev Reserve helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract ReserveHelpersStorage is Ownable2StepUpgradeable {\\n /// @notice Deprecated slot for assetReserves mapping\\n bytes32 private __deprecatedSlot1;\\n\\n /// @notice Available asset's fund per pool in RiskFund\\n /// Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) public poolAssetsFunds;\\n\\n /// @notice Deprecated slot for poolRegistry address\\n bytes32 private __deprecatedSlot2;\\n /// @notice Deprecated slot for status variable\\n bytes32 private __deprecatedSlot3;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n uint256[46] private __gap;\\n}\\n\\n/// @title MaxLoopsLimitHelpersStorage\\n/// @author Venus\\n/// @dev Max loop limit helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract MaxLoopsLimitHelpersStorage {\\n /// @notice Limit for the loops to avoid the DOS\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 public maxLoopsLimit;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[49] private __gap;\\n}\\n\\n/// @title RiskFundV1Storage\\n/// @author Venus\\n/// @dev Risk fund V1 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV1Storage is ReserveHelpersStorage, MaxLoopsLimitHelpersStorage {\\n /// @notice Address of base asset\\n address public convertibleBaseAsset;\\n /// @notice Address of shortfall contract\\n address public shortfall;\\n\\n /// @notice This state is deprecated, using it to prevent storage collision\\n address private pancakeSwapRouter;\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 private minAmountToConvert;\\n}\\n\\n/// @title RiskFundV2Storage\\n/// @author Venus\\n/// @dev Risk fund V2 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeable {\\n /// @notice Risk fund converter address\\n address public riskFundConverter;\\n}\\n\",\"keccak256\":\"0x0620187dca927191ab256ea20e42416883380690e54ba344807867adba01d7fb\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { IRiskFund } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IRiskFundConverter } from \\\"../Interfaces/IRiskFundConverter.sol\\\";\\nimport { RiskFundV2Storage } from \\\"./RiskFundStorage.sol\\\";\\n\\n/// @title RiskFundV2\\n/// @author Venus\\n/// @notice Contract with basic features to hold base asset for different Comptrollers\\n/// @dev This contract does not support BNB\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Emitted when convertible base asset address is updated\\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\\n\\n /// @notice Emitted when risk fund converter address is updated\\n event RiskFundConverterUpdated(address indexed oldRiskFundConverter, address indexed newRiskFundConverter);\\n\\n /// @notice Emitted when shortfall contract address is updated\\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\\n\\n /// @notice Emitted when reserves are transferred for auction\\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred to this contract\\n event PoolAssetsIncreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\\n event PoolAssetsDecreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Event emitted when tokens are swept and transferred from pool\\n event SweepTokenFromPool(address indexed token, address indexed comptroller, uint256 amount);\\n\\n /// @notice Error is thrown when updatePoolState is not called by riskFundConverter\\n error InvalidRiskFundConverter();\\n\\n /// @notice Error is thrown when transferReserveForAuction is called by non shortfall address\\n error InvalidShortfallAddress();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice Error is thrown when pool reserve is less than the amount needed\\n error InsufficientPoolReserve(address comptroller, uint256 amount, uint256 poolReserve);\\n\\n /// @dev Convertible base asset setter\\n /// @param convertibleBaseAsset_ Address of the convertible base asset\\n /// @custom:event ConvertibleBaseAssetUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\\n /// @custom:access Only Governance\\n function setConvertibleBaseAsset(address convertibleBaseAsset_) external onlyOwner {\\n ensureNonzeroAddress(convertibleBaseAsset_);\\n emit ConvertibleBaseAssetUpdated(convertibleBaseAsset, convertibleBaseAsset_);\\n convertibleBaseAsset = convertibleBaseAsset_;\\n }\\n\\n /// @dev Risk fund converter setter\\n /// @param riskFundConverter_ Address of the risk fund converter\\n /// @custom:event RiskFundConverterUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when risk fund converter address is zero\\n /// @custom:access Only Governance\\n function setRiskFundConverter(address riskFundConverter_) external onlyOwner {\\n ensureNonzeroAddress(riskFundConverter_);\\n emit RiskFundConverterUpdated(riskFundConverter, riskFundConverter_);\\n riskFundConverter = riskFundConverter_;\\n }\\n\\n /// @dev Shortfall contract address setter\\n /// @param shortfallContractAddress_ Address of the auction contract\\n /// @custom:event ShortfallContractUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n /// @custom:access Only Governance\\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\\n ensureNonzeroAddress(shortfallContractAddress_);\\n emit ShortfallContractUpdated(shortfall, shortfallContractAddress_);\\n shortfall = shortfallContractAddress_;\\n }\\n\\n /// @dev Transfer tokens for auction to shortfall contract\\n /// @param comptroller Comptroller of the pool\\n /// @param amount Amount to be transferred to the shortfall\\n /// @return Amount of tokens transferred to the shortfall\\n /// @custom:event TransferredReserveForAuction emit on success\\n /// @custom:error InvalidShortfallAddress is thrown when caller is not shortfall contract\\n /// @custom:error InsufficientPoolReserve is thrown when pool reserve is less than the amount needed\\n /// @custom:access Only Shortfall contract\\n function transferReserveForAuction(address comptroller, uint256 amount)\\n external\\n override\\n nonReentrant\\n returns (uint256)\\n {\\n uint256 poolReserve = poolAssetsFunds[comptroller][convertibleBaseAsset];\\n\\n if (msg.sender != shortfall) {\\n revert InvalidShortfallAddress();\\n }\\n if (amount > poolReserve) {\\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\\n }\\n\\n unchecked {\\n poolAssetsFunds[comptroller][convertibleBaseAsset] = poolReserve - amount;\\n }\\n\\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall, amount);\\n emit TransferredReserveForAuction(comptroller, amount);\\n\\n return amount;\\n }\\n\\n /// @notice Function to sweep baseAsset for pool, Tokens are sent to address(to)\\n /// @param tokenAddress Address of the asset(token)\\n /// @param to Address to which assets will be transferred\\n /// @param amount Amount need to sweep for the pool\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /// @notice Function to sweep token from pool\\n /// @param tokenAddress Address of the asset(token)\\n /// @param comptroller Pool address to which assets will be transferred\\n /// @param amount Amount need to sweep from the pool\\n /// @custom:event Emits sweepTokenFromPool event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zero\\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\\n /// @custom:access Only Governance\\n function sweepTokenFromPool(\\n address tokenAddress,\\n address comptroller,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(comptroller);\\n ensureNonzeroValue(amount);\\n\\n uint256 poolReserve = poolAssetsFunds[comptroller][tokenAddress];\\n\\n if (amount > poolReserve) {\\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\\n }\\n\\n unchecked {\\n poolAssetsFunds[comptroller][tokenAddress] = poolReserve - amount;\\n }\\n\\n IERC20Upgradeable(tokenAddress).safeTransfer(comptroller, amount);\\n\\n emit SweepTokenFromPool(tokenAddress, comptroller, amount);\\n }\\n\\n /**\\n * @notice Get the Amount of the Base asset in the risk fund for the specific pool.\\n * @param comptroller Comptroller address(pool).\\n * @return Base Asset's reserve in risk fund.\\n */\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256) {\\n return poolAssetsFunds[comptroller][convertibleBaseAsset];\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Address of the asset(token)\\n /// @param amount Amount transferred for the pool\\n /// @custom:event PoolAssetsIncreased emits on success\\n /// @custom:error InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\\n /// @custom:access Only RiskFundConverter contract\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) public {\\n if (msg.sender != riskFundConverter) {\\n revert InvalidRiskFundConverter();\\n }\\n\\n poolAssetsFunds[comptroller][asset] += amount;\\n emit PoolAssetsIncreased(comptroller, asset, amount);\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\\n function preSweepToken(address tokenAddress, uint256 amount) internal {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n\\n address[] memory pools = IRiskFundConverter(riskFundConverter).getPools(tokenAddress);\\n\\n uint256 assetReserves;\\n uint256 poolsLength = pools.length;\\n for (uint256 i; i < poolsLength; ) {\\n assetReserves += poolAssetsFunds[pools[i]][tokenAddress];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256 balanceDiff = balance - assetReserves;\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n uint256 distributedShare;\\n for (uint256 i; i < poolsLength; ) {\\n if (poolAssetsFunds[pools[i]][tokenAddress] != 0) {\\n uint256 poolAmountShare;\\n if (i < (poolsLength - 1)) {\\n poolAmountShare = (poolAssetsFunds[pools[i]][tokenAddress] * amount) / assetReserves;\\n distributedShare += poolAmountShare;\\n } else {\\n poolAmountShare = amountDiff - distributedShare;\\n }\\n poolAssetsFunds[pools[i]][tokenAddress] -= poolAmountShare;\\n emit PoolAssetsDecreased(pools[i], tokenAddress, poolAmountShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x311a4e348835634eaa4aaf08515f91552513cdf1f5a01c05bf75f939a294bf2e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506118db806100206000396000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c806377d4937f116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102ff578063e30c397814610313578063f2fde38b1461032457600080fd5b8063b4a0bdf3146102e5578063be26317e146102f657600080fd5b8063855a8dd2116100b2578063855a8dd2146102865780638da5cb5b14610299578063a69bd19e146102aa57600080fd5b806377d4937f1461026b57806379ba50971461027e57600080fd5b806353ac353711610124578063601bb5a911610109578063601bb5a91461023d57806364aff9ec14610250578063715018a61461026357600080fd5b806353ac3537146101ff5780635dbe35331461021257600080fd5b806319b1faef1161015557806319b1faef146101ac5780632e688141146101d85780632eef9172146101eb57600080fd5b80630a9837c5146101715780630e32cb8614610197575b600080fd5b61018461017f3660046114dc565b610337565b6040519081526020015b60405180910390f35b6101aa6101a5366004611508565b610496565b005b61012e546101c0906001600160a01b031681565b6040516001600160a01b03909116815260200161018e565b6101aa6101e6366004611508565b6104aa565b610163546101c0906001600160a01b031681565b6101aa61020d36600461152c565b610531565b61018461022036600461156d565b60ca60209081526000928352604080842090915290825290205481565b6101aa61024b366004611508565b610606565b6101aa61025e36600461152c565b61068d565b6101aa610735565b6101aa610279366004611508565b610749565b6101aa6107d0565b6101aa61029436600461152c565b610875565b6033546001600160a01b03166101c0565b6101846102b8366004611508565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101c0565b61018460fb5481565b61012d546101c0906001600160a01b031681565b6065546001600160a01b03166101c0565b6101aa610332366004611508565b610996565b6000610341610a1f565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e5490911633146103aa576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80831115610402576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461044692908116911685610a94565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161048191815260200190565b60405180910390a25050600161013155919050565b61049e610b14565b6104a781610b88565b50565b6104b2610b14565b6104bb81610c97565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610576576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca60209081526040808320938616835292905290812080548392906105ad9084906115d5565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105f991815260200190565b60405180910390a3505050565b61060e610b14565b61061781610c97565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610695610b14565b61069d610a1f565b6106a683610c97565b6106af82610c97565b6106b881610cd7565b826106c38183610d11565b6106d76001600160a01b0382168484610a94565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d58460405161071c91815260200190565b60405180910390a350610730600161013155565b505050565b61073d610b14565b6107476000611135565b565b610751610b14565b61075a81610c97565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461086c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103f9565b6104a781611135565b61087d610b14565b610885610a1f565b61088e83610c97565b61089782610c97565b6108a081610cd7565b6001600160a01b03808316600090815260ca602090815260408083209387168352929052205480821115610919576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260248101839052604481018290526064016103f9565b6001600160a01b03808416600090815260ca602090815260408083209388168084529390915290208383039055610951908484610a94565b826001600160a01b0316846001600160a01b03167f0e8a97dff226f3ada9da954f9bd38f73280b03ef851bfc7c97db1343f07bdbdc8460405161071c91815260200190565b61099e610b14565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556109e76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60026101315403610a8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103f9565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610730908490611166565b6033546001600160a01b03163314610747576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103f9565b6001600160a01b038116610c1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103f9565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b0381166104a7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000036104a7576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9591906115ed565b905080821115610dd1576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610e36573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610e7c9190810190611645565b8051909150600090815b81811015610f055760ca6000858381518110610ea457610ea4611728565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610efb91906115d5565b9250600101610e86565b506000610f128386611757565b90508581101561112c578086036000805b848110156111285760ca6000888381518110610f4157610f41611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014611120576000610fa1600187611757565b82101561103357868a60ca60008b8681518110610fc057610fc0611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054611016919061176e565b61102091906117ab565b905061102c81846115d5565b9250611040565b61103d8385611757565b90505b8060ca60008a858151811061105757611057611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546110b19190611757565b925050819055508a6001600160a01b03168883815181106110d4576110d4611728565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd843208360405161111691815260200190565b60405180910390a3505b600101610f23565b5050505b50505050505050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556104a781611268565b60006111bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166112d29092919063ffffffff16565b90508051600014806111dc5750808060200190518101906111dc91906117e6565b610730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103f9565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606112e184846000856112e9565b949350505050565b60608247101561137b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103f9565b600080866001600160a01b031685876040516113979190611838565b60006040518083038185875af1925050503d80600081146113d4576040519150601f19603f3d011682016040523d82523d6000602084013e6113d9565b606091505b50915091506113ea878383876113f5565b979650505050505050565b6060831561147e578251600003611477576001600160a01b0385163b611477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103f9565b50816112e1565b6112e183838151156114935781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f99190611854565b6001600160a01b03811681146104a757600080fd5b600080604083850312156114ef57600080fd5b82356114fa816114c7565b946020939093013593505050565b60006020828403121561151a57600080fd5b8135611525816114c7565b9392505050565b60008060006060848603121561154157600080fd5b833561154c816114c7565b9250602084013561155c816114c7565b929592945050506040919091013590565b6000806040838503121561158057600080fd5b823561158b816114c7565b9150602083013561159b816114c7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115e8576115e86115a6565b500190565b6000602082840312156115ff57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8051611640816114c7565b919050565b6000602080838503121561165857600080fd5b825167ffffffffffffffff8082111561167057600080fd5b818501915085601f83011261168457600080fd5b81518181111561169657611696611606565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811085821117156116d9576116d9611606565b6040529182528482019250838101850191888311156116f757600080fd5b938501935b8285101561171c5761170d85611635565b845293850193928501926116fc565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082821015611769576117696115a6565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156117a6576117a66115a6565b500290565b6000826117e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156117f857600080fd5b8151801515811461152557600080fd5b60005b8381101561182357818101518382015260200161180b565b83811115611832576000848401525b50505050565b6000825161184a818460208701611808565b9190910192915050565b6020815260008251806020840152611873816040850160208701611808565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220ae70b20469fe0d634614028f8d5ab4bd856fb444c39affcec03bff538f7033cd64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061016c5760003560e01c806377d4937f116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102ff578063e30c397814610313578063f2fde38b1461032457600080fd5b8063b4a0bdf3146102e5578063be26317e146102f657600080fd5b8063855a8dd2116100b2578063855a8dd2146102865780638da5cb5b14610299578063a69bd19e146102aa57600080fd5b806377d4937f1461026b57806379ba50971461027e57600080fd5b806353ac353711610124578063601bb5a911610109578063601bb5a91461023d57806364aff9ec14610250578063715018a61461026357600080fd5b806353ac3537146101ff5780635dbe35331461021257600080fd5b806319b1faef1161015557806319b1faef146101ac5780632e688141146101d85780632eef9172146101eb57600080fd5b80630a9837c5146101715780630e32cb8614610197575b600080fd5b61018461017f3660046114dc565b610337565b6040519081526020015b60405180910390f35b6101aa6101a5366004611508565b610496565b005b61012e546101c0906001600160a01b031681565b6040516001600160a01b03909116815260200161018e565b6101aa6101e6366004611508565b6104aa565b610163546101c0906001600160a01b031681565b6101aa61020d36600461152c565b610531565b61018461022036600461156d565b60ca60209081526000928352604080842090915290825290205481565b6101aa61024b366004611508565b610606565b6101aa61025e36600461152c565b61068d565b6101aa610735565b6101aa610279366004611508565b610749565b6101aa6107d0565b6101aa61029436600461152c565b610875565b6033546001600160a01b03166101c0565b6101846102b8366004611508565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101c0565b61018460fb5481565b61012d546101c0906001600160a01b031681565b6065546001600160a01b03166101c0565b6101aa610332366004611508565b610996565b6000610341610a1f565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e5490911633146103aa576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80831115610402576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461044692908116911685610a94565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161048191815260200190565b60405180910390a25050600161013155919050565b61049e610b14565b6104a781610b88565b50565b6104b2610b14565b6104bb81610c97565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610576576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca60209081526040808320938616835292905290812080548392906105ad9084906115d5565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105f991815260200190565b60405180910390a3505050565b61060e610b14565b61061781610c97565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610695610b14565b61069d610a1f565b6106a683610c97565b6106af82610c97565b6106b881610cd7565b826106c38183610d11565b6106d76001600160a01b0382168484610a94565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d58460405161071c91815260200190565b60405180910390a350610730600161013155565b505050565b61073d610b14565b6107476000611135565b565b610751610b14565b61075a81610c97565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461086c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103f9565b6104a781611135565b61087d610b14565b610885610a1f565b61088e83610c97565b61089782610c97565b6108a081610cd7565b6001600160a01b03808316600090815260ca602090815260408083209387168352929052205480821115610919576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260248101839052604481018290526064016103f9565b6001600160a01b03808416600090815260ca602090815260408083209388168084529390915290208383039055610951908484610a94565b826001600160a01b0316846001600160a01b03167f0e8a97dff226f3ada9da954f9bd38f73280b03ef851bfc7c97db1343f07bdbdc8460405161071c91815260200190565b61099e610b14565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556109e76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60026101315403610a8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103f9565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610730908490611166565b6033546001600160a01b03163314610747576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103f9565b6001600160a01b038116610c1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103f9565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b0381166104a7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000036104a7576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9591906115ed565b905080821115610dd1576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610e36573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610e7c9190810190611645565b8051909150600090815b81811015610f055760ca6000858381518110610ea457610ea4611728565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610efb91906115d5565b9250600101610e86565b506000610f128386611757565b90508581101561112c578086036000805b848110156111285760ca6000888381518110610f4157610f41611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014611120576000610fa1600187611757565b82101561103357868a60ca60008b8681518110610fc057610fc0611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054611016919061176e565b61102091906117ab565b905061102c81846115d5565b9250611040565b61103d8385611757565b90505b8060ca60008a858151811061105757611057611728565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546110b19190611757565b925050819055508a6001600160a01b03168883815181106110d4576110d4611728565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd843208360405161111691815260200190565b60405180910390a3505b600101610f23565b5050505b50505050505050565b606580547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556104a781611268565b60006111bb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166112d29092919063ffffffff16565b90508051600014806111dc5750808060200190518101906111dc91906117e6565b610730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103f9565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606112e184846000856112e9565b949350505050565b60608247101561137b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103f9565b600080866001600160a01b031685876040516113979190611838565b60006040518083038185875af1925050503d80600081146113d4576040519150601f19603f3d011682016040523d82523d6000602084013e6113d9565b606091505b50915091506113ea878383876113f5565b979650505050505050565b6060831561147e578251600003611477576001600160a01b0385163b611477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103f9565b50816112e1565b6112e183838151156114935781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f99190611854565b6001600160a01b03811681146104a757600080fd5b600080604083850312156114ef57600080fd5b82356114fa816114c7565b946020939093013593505050565b60006020828403121561151a57600080fd5b8135611525816114c7565b9392505050565b60008060006060848603121561154157600080fd5b833561154c816114c7565b9250602084013561155c816114c7565b929592945050506040919091013590565b6000806040838503121561158057600080fd5b823561158b816114c7565b9150602083013561159b816114c7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115e8576115e86115a6565b500190565b6000602082840312156115ff57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8051611640816114c7565b919050565b6000602080838503121561165857600080fd5b825167ffffffffffffffff8082111561167057600080fd5b818501915085601f83011261168457600080fd5b81518181111561169657611696611606565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811085821117156116d9576116d9611606565b6040529182528482019250838101850191888311156116f757600080fd5b938501935b8285101561171c5761170d85611635565b845293850193928501926116fc565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082821015611769576117696115a6565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156117a6576117a66115a6565b500290565b6000826117e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156117f857600080fd5b8151801515811461152557600080fd5b60005b8381101561182357818101518382015260200161180b565b83811115611832576000848401525b50505050565b6000825161184a818460208701611808565b9190910192915050565b6020815260008251806020840152611873816040850160208701611808565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220ae70b20469fe0d634614028f8d5ab4bd856fb444c39affcec03bff538f7033cd64736f6c634300080d0033", + "devdoc": { + "author": "Venus", + "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", + "details": "This contract does not support BNB", + "kind": "dev", + "methods": { + "acceptOwnership()": { + "details": "The new owner accepts the ownership transfer." + }, + "getPoolsBaseAssetReserves(address)": { + "params": { + "comptroller": "Comptroller address(pool)." + }, + "returns": { + "_0": "Base Asset's reserve in risk fund." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pendingOwner()": { + "details": "Returns the address of the pending owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setAccessControlManager(address)": { + "custom:access": "Only Governance", + "custom:event": "Emits NewAccessControlManager event", + "details": "Admin function to set address of AccessControlManager", + "params": { + "accessControlManager_": "The new address of the AccessControlManager" + } + }, + "setConvertibleBaseAsset(address)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when convertible base asset address is zero", + "custom:event": "ConvertibleBaseAssetUpdated emit on success", + "details": "Convertible base asset setter", + "params": { + "convertibleBaseAsset_": "Address of the convertible base asset" + } + }, + "setRiskFundConverter(address)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when risk fund converter address is zero", + "custom:event": "RiskFundConverterUpdated emit on success", + "details": "Risk fund converter setter", + "params": { + "riskFundConverter_": "Address of the risk fund converter" + } + }, + "setShortfallContractAddress(address)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when shortfall contract address is zero", + "custom:event": "ShortfallContractUpdated emit on success", + "details": "Shortfall contract address setter", + "params": { + "shortfallContractAddress_": "Address of the auction contract" + } + }, + "sweepToken(address,address,uint256)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when tokenAddress/to address is zeroZeroValueNotAllowed is thrown when amount is zero", + "custom:event": "Emits SweepToken event on success", + "params": { + "amount": "Amount need to sweep for the pool", + "to": "Address to which assets will be transferred", + "tokenAddress": "Address of the asset(token)" + } + }, + "sweepTokenFromPool(address,address,uint256)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when tokenAddress/comptroller address is zeroZeroValueNotAllowed is thrown when amount is zero", + "custom:event": "Emits sweepTokenFromPool event on success", + "params": { + "amount": "Amount need to sweep from the pool", + "comptroller": "Pool address to which assets will be transferred", + "tokenAddress": "Address of the asset(token)" + } + }, + "transferOwnership(address)": { + "details": "Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner." + }, + "transferReserveForAuction(address,uint256)": { + "custom:access": "Only Shortfall contract", + "custom:error": "InvalidShortfallAddress is thrown when caller is not shortfall contractInsufficientPoolReserve is thrown when pool reserve is less than the amount needed", + "custom:event": "TransferredReserveForAuction emit on success", + "details": "Transfer tokens for auction to shortfall contract", + "params": { + "amount": "Amount to be transferred to the shortfall", + "comptroller": "Comptroller of the pool" + }, + "returns": { + "_0": "Amount of tokens transferred to the shortfall" + } + }, + "updatePoolState(address,address,uint256)": { + "custom:access": "Only RiskFundConverter contract", + "custom:error": "InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract", + "custom:event": "PoolAssetsIncreased emits on success", + "details": "Update the reserve of the asset for the specific pool after transferring to risk fund", + "params": { + "amount": "Amount transferred for the pool", + "asset": "Address of the asset(token)", + "comptroller": "Comptroller address (pool)" + } + } + }, + "title": "RiskFundV2", + "version": 1 + }, + "userdoc": { + "errors": { + "InsufficientBalance()": [ + { + "notice": "thrown when amount entered is greater than balance" + } + ], + "InsufficientPoolReserve(address,uint256,uint256)": [ + { + "notice": "Error is thrown when pool reserve is less than the amount needed" + } + ], + "InvalidRiskFundConverter()": [ + { + "notice": "Error is thrown when updatePoolState is not called by riskFundConverter" + } + ], + "InvalidShortfallAddress()": [ + { + "notice": "Error is thrown when transferReserveForAuction is called by non shortfall address" + } + ], + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ], + "ZeroAddressNotAllowed()": [ + { + "notice": "Thrown if the supplied address is a zero address where it is not allowed" + } + ], + "ZeroValueNotAllowed()": [ + { + "notice": "Thrown if the supplied value is 0 where it is not allowed" + } + ] + }, + "events": { + "ConvertibleBaseAssetUpdated(address,address)": { + "notice": "Emitted when convertible base asset address is updated" + }, + "NewAccessControlManager(address,address)": { + "notice": "Emitted when access control manager contract address is changed" + }, + "PoolAssetsDecreased(address,address,uint256)": { + "notice": "Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens" + }, + "PoolAssetsIncreased(address,address,uint256)": { + "notice": "Emitted when pool asset states is updated with amount transferred to this contract" + }, + "RiskFundConverterUpdated(address,address)": { + "notice": "Emitted when risk fund converter address is updated" + }, + "ShortfallContractUpdated(address,address)": { + "notice": "Emitted when shortfall contract address is updated" + }, + "SweepToken(address,address,uint256)": { + "notice": "Event emitted when tokens are swept" + }, + "SweepTokenFromPool(address,address,uint256)": { + "notice": "Event emitted when tokens are swept and transferred from pool" + }, + "TransferredReserveForAuction(address,uint256)": { + "notice": "Emitted when reserves are transferred for auction" + } + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "Returns the address of the access control manager contract" + }, + "convertibleBaseAsset()": { + "notice": "Address of base asset" + }, + "getPoolsBaseAssetReserves(address)": { + "notice": "Get the Amount of the Base asset in the risk fund for the specific pool." + }, + "maxLoopsLimit()": { + "notice": "Limit for the loops to avoid the DOSThis state is deprecated, using it to prevent storage collision" + }, + "poolAssetsFunds(address,address)": { + "notice": "Available asset's fund per pool in RiskFund Comptroller(pool) -> Asset -> amount" + }, + "riskFundConverter()": { + "notice": "Risk fund converter address" + }, + "setAccessControlManager(address)": { + "notice": "Sets the address of AccessControlManager" + }, + "shortfall()": { + "notice": "Address of shortfall contract" + }, + "sweepToken(address,address,uint256)": { + "notice": "Function to sweep baseAsset for pool, Tokens are sent to address(to)" + }, + "sweepTokenFromPool(address,address,uint256)": { + "notice": "Function to sweep token from pool" + } + }, + "notice": "Contract with basic features to hold base asset for different Comptrollers", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 244, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 247, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1478, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 116, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 236, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 25, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_pendingOwner", + "offset": 0, + "slot": "101", + "type": "t_address" + }, + { + "astId": 104, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 4921, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_accessControlManager", + "offset": 0, + "slot": "151", + "type": "t_contract(IAccessControlManagerV8)5106" + }, + { + "astId": 4926, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 7563, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__deprecatedSlot1", + "offset": 0, + "slot": "201", + "type": "t_bytes32" + }, + { + "astId": 7570, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "poolAssetsFunds", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 7573, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__deprecatedSlot2", + "offset": 0, + "slot": "203", + "type": "t_bytes32" + }, + { + "astId": 7576, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__deprecatedSlot3", + "offset": 0, + "slot": "204", + "type": "t_bytes32" + }, + { + "astId": 7581, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "205", + "type": "t_array(t_uint256)46_storage" + }, + { + "astId": 7586, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "maxLoopsLimit", + "offset": 0, + "slot": "251", + "type": "t_uint256" + }, + { + "astId": 7591, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 7600, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "convertibleBaseAsset", + "offset": 0, + "slot": "301", + "type": "t_address" + }, + { + "astId": 7603, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "shortfall", + "offset": 0, + "slot": "302", + "type": "t_address" + }, + { + "astId": 7606, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "pancakeSwapRouter", + "offset": 0, + "slot": "303", + "type": "t_address" + }, + { + "astId": 7609, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "minAmountToConvert", + "offset": 0, + "slot": "304", + "type": "t_uint256" + }, + { + "astId": 547, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_status", + "offset": 0, + "slot": "305", + "type": "t_uint256" + }, + { + "astId": 616, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "306", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 7618, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "riskFundConverter", + "offset": 0, + "slot": "355", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)46_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[46]", + "numberOfBytes": "1472" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IAccessControlManagerV8)5106": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} diff --git a/deployments/bscmainnet/RiskFundV2_Proxy.json b/deployments/bscmainnet/RiskFundV2_Proxy.json new file mode 100644 index 00000000..af7e00d3 --- /dev/null +++ b/deployments/bscmainnet/RiskFundV2_Proxy.json @@ -0,0 +1,277 @@ +{ + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "receipt": { + "to": null, + "from": "0x55A9f5374Af30E3045FB491f1da3C2E8a74d168D", + "contractAddress": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "transactionIndex": 49, + "gasUsed": "888558", + "logsBloom": "0x00000000010000000000000000000000400000000000000000800000000000000000000000000000000000000000000000200000000000000000000000008000000000000000000000000000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000000000020000000400000000080000000000000800000000000000000000000002000000400000000000000800000000000000000000000000020000020000000000001040000400000000400000000000000001020000000000200000000000000000000000000000800000000000400000000020000", + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67", + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "logs": [ + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x00000000000000000000000087ac8dd81ec00d2183a04d22884e7fc67f6ce0c8" + ], + "data": "0x", + "logIndex": 87, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + }, + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000055a9f5374af30e3045fb491f1da3c2e8a74d168d" + ], + "data": "0x", + "logIndex": 88, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + }, + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 89, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + }, + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 90, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + }, + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 91, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + }, + { + "transactionIndex": 49, + "blockNumber": 31670886, + "transactionHash": "0xae915a962973c42c5c57c1996d903612f73792b1d2593b6732ede95c9aa96bc3", + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006beb6d2695b67feb73ad4f172e8e2975497187e4", + "logIndex": 92, + "blockHash": "0x257df431491cd4263b736de0d3b3eb095a88e52ef7be61d7b6f0195be0c46d67" + } + ], + "blockNumber": 31670886, + "cumulativeGasUsed": "5316071", + "status": 1, + "byzantium": true + }, + "args": [ + "0x87ac8dD81Ec00D2183a04D22884e7FC67f6ce0C8", + "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4", + "0x2a1d05470000000000000000000000008938e6da30b59c1e27d5f70a94688a89f7c815a40000000000000000000000000000000000000000000000008ac7230489e8000000000000000000000000000055d398326f99059ff775485246999027b31979550000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c235550000000000000000000000000000000000000000000000000000000000000064" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/bsctestnet/RiskFundV2.json b/deployments/bsctestnet/RiskFundV2.json index f0e63bde..1df3ad03 100644 --- a/deployments/bsctestnet/RiskFundV2.json +++ b/deployments/bsctestnet/RiskFundV2.json @@ -1,6 +1,150 @@ { - "address": "0xcA2A023FBe3be30b7187E88D7FDE1A9a4358B509", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, { "inputs": [], "name": "InsufficientBalance", @@ -270,6 +414,31 @@ "name": "SweepToken", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepTokenFromPool", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -512,6 +681,29 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepTokenFromPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -573,477 +765,143 @@ "type": "function" } ], - "transactionHash": "0xe099e07b1b29bbec08be51fdd4ba175e5c2be6b14f6ae5c47bea363149d735cd", + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", "receipt": { "to": null, - "from": "0x02EB950C215D12d723b44a18CfF098C6E166C531", - "contractAddress": "0xcA2A023FBe3be30b7187E88D7FDE1A9a4358B509", - "transactionIndex": 0, - "gasUsed": "1345902", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x719459c15feafb725beb928a8991f96cd52c5049a7e6be1bd4b3137521a8bd79", - "transactionHash": "0xe099e07b1b29bbec08be51fdd4ba175e5c2be6b14f6ae5c47bea363149d735cd", - "logs": [], - "blockNumber": 36750922, - "cumulativeGasUsed": "1345902", + "from": "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706", + "contractAddress": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "transactionIndex": 2, + "gasUsed": "888546", + "logsBloom": "0x1000000000000000000000000000000040000000000000000080000800000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000000000000000000000000000081000000000000800000000000000000800000002000008400000000000000800000000000000000002000000020000000000000000001040000000000004400000000000000000020000000000200000000000000002000000000000800000000000000000000000000", + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e", + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000665085ecc7bc1b59c9872d030f2bd6c724739709" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + }, + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000002ce1d0ffd7e869d9df33e28552b12ddded326706" + ], + "data": "0x", + "logIndex": 2, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + }, + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 3, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + }, + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 4, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + }, + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 5, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + }, + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007877ffd62649b6a1557b55d4c20fcbab17344c91", + "logIndex": 6, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + } + ], + "blockNumber": 33267915, + "cumulativeGasUsed": "1000882", "status": 1, "byzantium": true }, - "args": [], + "args": [ + "0x665085EcC7bc1B59c9872d030f2Bd6c724739709", + "0x7877fFd62649b6A1557B55D4c20fcBaB17344C91", + "0x2a1d054700000000000000000000000083edf1dee1b730b7e8e13c00ba76027d63a51ac00000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000000000a11c8d9dc9b66e209ef60f0c8d969d3cd988782c00000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa0000000000000000000000000000000000000000000000000000000000000064" + ], "numDeployments": 1, - "solcInputHash": "ee8827a99e03cdf6f6a94fb8782ddf44", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"poolReserve\",\"type\":\"uint256\"}],\"name\":\"InsufficientPoolReserve\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRiskFundConverter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortfallAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsDecreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldRiskFundConverter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newRiskFundConverter\",\"type\":\"address\"}],\"name\":\"RiskFundConverterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newShortfallContract\",\"type\":\"address\"}],\"name\":\"ShortfallContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLoopsLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolAssetsFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"riskFundConverter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"riskFundConverter_\",\"type\":\"address\"}],\"name\":\"setRiskFundConverter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"updatePoolState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"details\":\"This contract does not support BNB\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"custom:event\":\"ConvertibleBaseAssetUpdated emit on success\",\"details\":\"Convertible base asset setter\",\"params\":{\"convertibleBaseAsset_\":\"Address of the convertible base asset\"}},\"setRiskFundConverter(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when risk fund converter address is zero\",\"custom:event\":\"RiskFundConverterUpdated emit on success\",\"details\":\"Risk fund converter setter\",\"params\":{\"riskFundConverter_\":\"Address of the risk fund converter\"}},\"setShortfallContractAddress(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"custom:event\":\"ShortfallContractUpdated emit on success\",\"details\":\"Shortfall contract address setter\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zeroZeroValueNotAllowed is thrown when amount is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"Amount need to sweep for the pool\",\"to\":\"Address to which assets will be transferred\",\"tokenAddress\":\"Address of the asset(token)\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"transferReserveForAuction(address,uint256)\":{\"custom:access\":\"Only Shortfall contract\",\"custom:error\":\"InvalidShortfallAddress is thrown when caller is not shortfall contractInsufficientPoolReserve is thrown when pool reserve is less than the amount needed\",\"custom:event\":\"TransferredReserveForAuction emit on success\",\"details\":\"Transfer tokens for auction to shortfall contract\",\"params\":{\"amount\":\"Amount to be transferred to the shortfall\",\"comptroller\":\"Comptroller of the pool\"},\"returns\":{\"_0\":\"Amount of tokens transferred to the shortfall\"}},\"updatePoolState(address,address,uint256)\":{\"custom:access\":\"Only RiskFundConverter contract\",\"custom:error\":\"InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\",\"custom:event\":\"PoolAssetsIncreased emits on success\",\"details\":\"Update the reserve of the asset for the specific pool after transferring to risk fund\",\"params\":{\"amount\":\"Amount transferred for the pool\",\"asset\":\"Address of the asset(token)\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"RiskFundV2\",\"version\":1},\"userdoc\":{\"errors\":{\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientPoolReserve(address,uint256,uint256)\":[{\"notice\":\"Error is thrown when pool reserve is less than the amount needed\"}],\"InvalidRiskFundConverter()\":[{\"notice\":\"Error is thrown when updatePoolState is not called by riskFundConverter\"}],\"InvalidShortfallAddress()\":[{\"notice\":\"Error is thrown when transferReserveForAuction is called by non shortfall address\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset address is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDecreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\"},\"PoolAssetsIncreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred to this contract\"},\"RiskFundConverterUpdated(address,address)\":{\"notice\":\"Emitted when risk fund converter address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"convertibleBaseAsset()\":{\"notice\":\"Address of base asset\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"maxLoopsLimit()\":{\"notice\":\"Limit for the loops to avoid the DOSThis state is deprecated, using it to prevent storage collision\"},\"poolAssetsFunds(address,address)\":{\"notice\":\"Available asset's fund per pool in RiskFund Comptroller(pool) -> Asset -> amount\"},\"riskFundConverter()\":{\"notice\":\"Risk fund converter address\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"shortfall()\":{\"notice\":\"Address of shortfall contract\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"Function to sweep baseAsset for pool, Tokens are sent to address(to)\"}},\"notice\":\"Contract with basic features to hold base asset for different Comptrollers\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ProtocolReserve/RiskFundV2.sol\":\"RiskFundV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IRiskFundConverter {\\n function updateAssetsState(address comptroller, address asset) external;\\n\\n function getPools(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb7335d0d343100ca6294c5858193f52462d1818212ff4435c14da961af87a39e\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\n\\n/// @title ReserveHelpersStorage\\n/// @author Venus\\n/// @dev Reserve helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract ReserveHelpersStorage is Ownable2StepUpgradeable {\\n /// @notice Deprecated slot for assetReserves mapping\\n bytes32 private __deprecatedSlot1;\\n\\n /// @notice Available asset's fund per pool in RiskFund\\n /// Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) public poolAssetsFunds;\\n\\n /// @notice Deprecated slot for poolRegistry address\\n bytes32 private __deprecatedSlot2;\\n /// @notice Deprecated slot for status variable\\n bytes32 private __deprecatedSlot3;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n uint256[46] private __gap;\\n}\\n\\n/// @title MaxLoopsLimitHelpersStorage\\n/// @author Venus\\n/// @dev Max loop limit helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract MaxLoopsLimitHelpersStorage {\\n /// @notice Limit for the loops to avoid the DOS\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 public maxLoopsLimit;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[49] private __gap;\\n}\\n\\n/// @title RiskFundV1Storage\\n/// @author Venus\\n/// @dev Risk fund V1 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV1Storage is ReserveHelpersStorage, MaxLoopsLimitHelpersStorage {\\n /// @notice Address of base asset\\n address public convertibleBaseAsset;\\n /// @notice Address of shortfall contract\\n address public shortfall;\\n\\n /// @notice This state is deprecated, using it to prevent storage collision\\n address private pancakeSwapRouter;\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 private minAmountToConvert;\\n}\\n\\n/// @title RiskFundV2Storage\\n/// @author Venus\\n/// @dev Risk fund V2 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeable {\\n /// @notice Risk fund converter address\\n address public riskFundConverter;\\n}\\n\",\"keccak256\":\"0x0620187dca927191ab256ea20e42416883380690e54ba344807867adba01d7fb\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { IRiskFund } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IRiskFundConverter } from \\\"../Interfaces/IRiskFundConverter.sol\\\";\\nimport { RiskFundV2Storage } from \\\"./RiskFundStorage.sol\\\";\\n\\n/// @title RiskFundV2\\n/// @author Venus\\n/// @notice Contract with basic features to hold base asset for different Comptrollers\\n/// @dev This contract does not support BNB\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Emitted when convertible base asset address is updated\\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\\n\\n /// @notice Emitted when risk fund converter address is updated\\n event RiskFundConverterUpdated(address indexed oldRiskFundConverter, address indexed newRiskFundConverter);\\n\\n /// @notice Emitted when shortfall contract address is updated\\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\\n\\n /// @notice Emitted when reserves are transferred for auction\\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred to this contract\\n event PoolAssetsIncreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\\n event PoolAssetsDecreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Error is thrown when updatePoolState is not called by riskFundConverter\\n error InvalidRiskFundConverter();\\n\\n /// @notice Error is thrown when transferReserveForAuction is called by non shortfall address\\n error InvalidShortfallAddress();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice Error is thrown when pool reserve is less than the amount needed\\n error InsufficientPoolReserve(address comptroller, uint256 amount, uint256 poolReserve);\\n\\n /// @dev Convertible base asset setter\\n /// @param convertibleBaseAsset_ Address of the convertible base asset\\n /// @custom:event ConvertibleBaseAssetUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\\n /// @custom:access Only Governance\\n function setConvertibleBaseAsset(address convertibleBaseAsset_) external onlyOwner {\\n ensureNonzeroAddress(convertibleBaseAsset_);\\n emit ConvertibleBaseAssetUpdated(convertibleBaseAsset, convertibleBaseAsset_);\\n convertibleBaseAsset = convertibleBaseAsset_;\\n }\\n\\n /// @dev Risk fund converter setter\\n /// @param riskFundConverter_ Address of the risk fund converter\\n /// @custom:event RiskFundConverterUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when risk fund converter address is zero\\n /// @custom:access Only Governance\\n function setRiskFundConverter(address riskFundConverter_) external onlyOwner {\\n ensureNonzeroAddress(riskFundConverter_);\\n emit RiskFundConverterUpdated(riskFundConverter, riskFundConverter_);\\n riskFundConverter = riskFundConverter_;\\n }\\n\\n /// @dev Shortfall contract address setter\\n /// @param shortfallContractAddress_ Address of the auction contract\\n /// @custom:event ShortfallContractUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n /// @custom:access Only Governance\\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\\n ensureNonzeroAddress(shortfallContractAddress_);\\n emit ShortfallContractUpdated(shortfall, shortfallContractAddress_);\\n shortfall = shortfallContractAddress_;\\n }\\n\\n /// @dev Transfer tokens for auction to shortfall contract\\n /// @param comptroller Comptroller of the pool\\n /// @param amount Amount to be transferred to the shortfall\\n /// @return Amount of tokens transferred to the shortfall\\n /// @custom:event TransferredReserveForAuction emit on success\\n /// @custom:error InvalidShortfallAddress is thrown when caller is not shortfall contract\\n /// @custom:error InsufficientPoolReserve is thrown when pool reserve is less than the amount needed\\n /// @custom:access Only Shortfall contract\\n function transferReserveForAuction(address comptroller, uint256 amount)\\n external\\n override\\n nonReentrant\\n returns (uint256)\\n {\\n uint256 poolReserve = poolAssetsFunds[comptroller][convertibleBaseAsset];\\n\\n if (msg.sender != shortfall) {\\n revert InvalidShortfallAddress();\\n }\\n if (amount > poolReserve) {\\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\\n }\\n\\n unchecked {\\n poolAssetsFunds[comptroller][convertibleBaseAsset] = poolReserve - amount;\\n }\\n\\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall, amount);\\n emit TransferredReserveForAuction(comptroller, amount);\\n\\n return amount;\\n }\\n\\n /// @notice Function to sweep baseAsset for pool, Tokens are sent to address(to)\\n /// @param tokenAddress Address of the asset(token)\\n /// @param to Address to which assets will be transferred\\n /// @param amount Amount need to sweep for the pool\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /**\\n * @notice Get the Amount of the Base asset in the risk fund for the specific pool.\\n * @param comptroller Comptroller address(pool).\\n * @return Base Asset's reserve in risk fund.\\n */\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256) {\\n return poolAssetsFunds[comptroller][convertibleBaseAsset];\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Address of the asset(token)\\n /// @param amount Amount transferred for the pool\\n /// @custom:event PoolAssetsIncreased emits on success\\n /// @custom:error InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\\n /// @custom:access Only RiskFundConverter contract\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) public {\\n if (msg.sender != riskFundConverter) {\\n revert InvalidRiskFundConverter();\\n }\\n\\n poolAssetsFunds[comptroller][asset] += amount;\\n emit PoolAssetsIncreased(comptroller, asset, amount);\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\\n function preSweepToken(address tokenAddress, uint256 amount) internal {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n\\n address[] memory pools = IRiskFundConverter(riskFundConverter).getPools(tokenAddress);\\n\\n uint256 assetReserves;\\n uint256 poolsLength = pools.length;\\n for (uint256 i; i < poolsLength; ) {\\n assetReserves += poolAssetsFunds[pools[i]][tokenAddress];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256 balanceDiff = balance - assetReserves;\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n uint256 distributedShare;\\n for (uint256 i; i < poolsLength; ) {\\n if (poolAssetsFunds[pools[i]][tokenAddress] != 0) {\\n uint256 poolAmountShare;\\n if (i < (poolsLength - 1)) {\\n poolAmountShare = (poolAssetsFunds[pools[i]][tokenAddress] * amount) / assetReserves;\\n distributedShare += poolAmountShare;\\n } else {\\n poolAmountShare = amountDiff - distributedShare;\\n }\\n poolAssetsFunds[pools[i]][tokenAddress] -= poolAmountShare;\\n emit PoolAssetsDecreased(pools[i], tokenAddress, poolAmountShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe79f3802602fe5b406a3c374360009eb92e9545aee1ac833916af6c749979a0e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061178c806100206000396000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063715018a6116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102d1578063e30c3978146102e5578063f2fde38b146102f657600080fd5b8063b4a0bdf3146102b7578063be26317e146102c857600080fd5b806379ba5097116100b257806379ba5097146102635780638da5cb5b1461026b578063a69bd19e1461027c57600080fd5b8063715018a61461024857806377d4937f1461025057600080fd5b80632eef9172116101245780635dbe3533116101095780635dbe3533146101f7578063601bb5a91461022257806364aff9ec1461023557600080fd5b80632eef9172146101d057806353ac3537146101e457600080fd5b80630a9837c5146101565780630e32cb861461017c57806319b1faef146101915780632e688141146101bd575b600080fd5b61016961016436600461138d565b610309565b6040519081526020015b60405180910390f35b61018f61018a3660046113b9565b610468565b005b61012e546101a5906001600160a01b031681565b6040516001600160a01b039091168152602001610173565b61018f6101cb3660046113b9565b61047c565b610163546101a5906001600160a01b031681565b61018f6101f23660046113dd565b610503565b61016961020536600461141e565b60ca60209081526000928352604080842090915290825290205481565b61018f6102303660046113b9565b6105d8565b61018f6102433660046113dd565b61065f565b61018f610707565b61018f61025e3660046113b9565b61071b565b61018f6107a2565b6033546001600160a01b03166101a5565b61016961028a3660046113b9565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101a5565b61016960fb5481565b61012d546101a5906001600160a01b031681565b6065546001600160a01b03166101a5565b61018f6103043660046113b9565b610847565b60006103136108d0565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e54909116331461037c576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808311156103d4576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461041892908116911685610945565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161045391815260200190565b60405180910390a25050600161013155919050565b6104706109c5565b61047981610a39565b50565b6104846109c5565b61048d81610b48565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610548576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca602090815260408083209386168352929052908120805483929061057f908490611486565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105cb91815260200190565b60405180910390a3505050565b6105e06109c5565b6105e981610b48565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6106676109c5565b61066f6108d0565b61067883610b48565b61068182610b48565b61068a81610b88565b826106958183610bc2565b6106a96001600160a01b0382168484610945565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516106ee91815260200190565b60405180910390a350610702600161013155565b505050565b61070f6109c5565b6107196000610fe6565b565b6107236109c5565b61072c81610b48565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461083e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103cb565b61047981610fe6565b61084f6109c5565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556108986033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002610131540361093d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103cb565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610702908490611017565b6033546001600160a01b03163314610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103cb565b6001600160a01b038116610acf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103cb565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b038116610479576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003610479576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610c22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c46919061149e565b905080821115610c82576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610ce7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610d2d91908101906114f6565b8051909150600090815b81811015610db65760ca6000858381518110610d5557610d556115d9565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610dac9190611486565b9250600101610d37565b506000610dc38386611608565b905085811015610fdd578086036000805b84811015610fd95760ca6000888381518110610df257610df26115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014610fd1576000610e52600187611608565b821015610ee457868a60ca60008b8681518110610e7157610e716115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054610ec7919061161f565b610ed1919061165c565b9050610edd8184611486565b9250610ef1565b610eee8385611608565b90505b8060ca60008a8581518110610f0857610f086115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b031681526020019081526020016000206000828254610f629190611608565b925050819055508a6001600160a01b0316888381518110610f8557610f856115d9565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd8432083604051610fc791815260200190565b60405180910390a3505b600101610dd4565b5050505b50505050505050565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561047981611119565b600061106c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111839092919063ffffffff16565b905080516000148061108d57508080602001905181019061108d9190611697565b610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103cb565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060611192848460008561119a565b949350505050565b60608247101561122c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103cb565b600080866001600160a01b0316858760405161124891906116e9565b60006040518083038185875af1925050503d8060008114611285576040519150601f19603f3d011682016040523d82523d6000602084013e61128a565b606091505b509150915061129b878383876112a6565b979650505050505050565b6060831561132f578251600003611328576001600160a01b0385163b611328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103cb565b5081611192565b61119283838151156113445781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103cb9190611705565b6001600160a01b038116811461047957600080fd5b600080604083850312156113a057600080fd5b82356113ab81611378565b946020939093013593505050565b6000602082840312156113cb57600080fd5b81356113d681611378565b9392505050565b6000806000606084860312156113f257600080fd5b83356113fd81611378565b9250602084013561140d81611378565b929592945050506040919091013590565b6000806040838503121561143157600080fd5b823561143c81611378565b9150602083013561144c81611378565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561149957611499611457565b500190565b6000602082840312156114b057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80516114f181611378565b919050565b6000602080838503121561150957600080fd5b825167ffffffffffffffff8082111561152157600080fd5b818501915085601f83011261153557600080fd5b815181811115611547576115476114b7565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561158a5761158a6114b7565b6040529182528482019250838101850191888311156115a857600080fd5b938501935b828510156115cd576115be856114e6565b845293850193928501926115ad565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008282101561161a5761161a611457565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561165757611657611457565b500290565b600082611692577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156116a957600080fd5b815180151581146113d657600080fd5b60005b838110156116d45781810151838201526020016116bc565b838111156116e3576000848401525b50505050565b600082516116fb8184602087016116b9565b9190910192915050565b60208152600082518060208401526117248160408501602087016116b9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea26469706673582212209c38201c74c3ca466d0abbc6a00c9bd8bb8ed5a5a063d3202f59106f43fcc5a764736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063715018a6116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102d1578063e30c3978146102e5578063f2fde38b146102f657600080fd5b8063b4a0bdf3146102b7578063be26317e146102c857600080fd5b806379ba5097116100b257806379ba5097146102635780638da5cb5b1461026b578063a69bd19e1461027c57600080fd5b8063715018a61461024857806377d4937f1461025057600080fd5b80632eef9172116101245780635dbe3533116101095780635dbe3533146101f7578063601bb5a91461022257806364aff9ec1461023557600080fd5b80632eef9172146101d057806353ac3537146101e457600080fd5b80630a9837c5146101565780630e32cb861461017c57806319b1faef146101915780632e688141146101bd575b600080fd5b61016961016436600461138d565b610309565b6040519081526020015b60405180910390f35b61018f61018a3660046113b9565b610468565b005b61012e546101a5906001600160a01b031681565b6040516001600160a01b039091168152602001610173565b61018f6101cb3660046113b9565b61047c565b610163546101a5906001600160a01b031681565b61018f6101f23660046113dd565b610503565b61016961020536600461141e565b60ca60209081526000928352604080842090915290825290205481565b61018f6102303660046113b9565b6105d8565b61018f6102433660046113dd565b61065f565b61018f610707565b61018f61025e3660046113b9565b61071b565b61018f6107a2565b6033546001600160a01b03166101a5565b61016961028a3660046113b9565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101a5565b61016960fb5481565b61012d546101a5906001600160a01b031681565b6065546001600160a01b03166101a5565b61018f6103043660046113b9565b610847565b60006103136108d0565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e54909116331461037c576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808311156103d4576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461041892908116911685610945565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161045391815260200190565b60405180910390a25050600161013155919050565b6104706109c5565b61047981610a39565b50565b6104846109c5565b61048d81610b48565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610548576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca602090815260408083209386168352929052908120805483929061057f908490611486565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105cb91815260200190565b60405180910390a3505050565b6105e06109c5565b6105e981610b48565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6106676109c5565b61066f6108d0565b61067883610b48565b61068182610b48565b61068a81610b88565b826106958183610bc2565b6106a96001600160a01b0382168484610945565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516106ee91815260200190565b60405180910390a350610702600161013155565b505050565b61070f6109c5565b6107196000610fe6565b565b6107236109c5565b61072c81610b48565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461083e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103cb565b61047981610fe6565b61084f6109c5565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556108986033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002610131540361093d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103cb565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610702908490611017565b6033546001600160a01b03163314610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103cb565b6001600160a01b038116610acf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103cb565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b038116610479576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003610479576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610c22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c46919061149e565b905080821115610c82576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610ce7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610d2d91908101906114f6565b8051909150600090815b81811015610db65760ca6000858381518110610d5557610d556115d9565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610dac9190611486565b9250600101610d37565b506000610dc38386611608565b905085811015610fdd578086036000805b84811015610fd95760ca6000888381518110610df257610df26115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014610fd1576000610e52600187611608565b821015610ee457868a60ca60008b8681518110610e7157610e716115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054610ec7919061161f565b610ed1919061165c565b9050610edd8184611486565b9250610ef1565b610eee8385611608565b90505b8060ca60008a8581518110610f0857610f086115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b031681526020019081526020016000206000828254610f629190611608565b925050819055508a6001600160a01b0316888381518110610f8557610f856115d9565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd8432083604051610fc791815260200190565b60405180910390a3505b600101610dd4565b5050505b50505050505050565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561047981611119565b600061106c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111839092919063ffffffff16565b905080516000148061108d57508080602001905181019061108d9190611697565b610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103cb565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060611192848460008561119a565b949350505050565b60608247101561122c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103cb565b600080866001600160a01b0316858760405161124891906116e9565b60006040518083038185875af1925050503d8060008114611285576040519150601f19603f3d011682016040523d82523d6000602084013e61128a565b606091505b509150915061129b878383876112a6565b979650505050505050565b6060831561132f578251600003611328576001600160a01b0385163b611328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103cb565b5081611192565b61119283838151156113445781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103cb9190611705565b6001600160a01b038116811461047957600080fd5b600080604083850312156113a057600080fd5b82356113ab81611378565b946020939093013593505050565b6000602082840312156113cb57600080fd5b81356113d681611378565b9392505050565b6000806000606084860312156113f257600080fd5b83356113fd81611378565b9250602084013561140d81611378565b929592945050506040919091013590565b6000806040838503121561143157600080fd5b823561143c81611378565b9150602083013561144c81611378565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561149957611499611457565b500190565b6000602082840312156114b057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80516114f181611378565b919050565b6000602080838503121561150957600080fd5b825167ffffffffffffffff8082111561152157600080fd5b818501915085601f83011261153557600080fd5b815181811115611547576115476114b7565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561158a5761158a6114b7565b6040529182528482019250838101850191888311156115a857600080fd5b938501935b828510156115cd576115be856114e6565b845293850193928501926115ad565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008282101561161a5761161a611457565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561165757611657611457565b500290565b600082611692577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156116a957600080fd5b815180151581146113d657600080fd5b60005b838110156116d45781810151838201526020016116bc565b838111156116e3576000848401525b50505050565b600082516116fb8184602087016116b9565b9190910192915050565b60208152600082518060208401526117248160408501602087016116b9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea26469706673582212209c38201c74c3ca466d0abbc6a00c9bd8bb8ed5a5a063d3202f59106f43fcc5a764736f6c634300080d0033", + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "execute": { + "methodName": "initialize", + "args": [ + "0x83edf1deE1B730b7e8e13C00ba76027D63a51ac0", + "10000000000000000000", + "0xA11c8D9DC9b66E209Ef60F0C8D969D3CD988782c", + "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA", + 100 + ] + }, + "implementation": "0x665085EcC7bc1B59c9872d030f2Bd6c724739709", "devdoc": { - "author": "Venus", - "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", - "details": "This contract does not support BNB", + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", "kind": "dev", "methods": { - "acceptOwnership()": { - "details": "The new owner accepts the ownership transfer." + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" }, - "getPoolsBaseAssetReserves(address)": { - "params": { - "comptroller": "Comptroller address(pool)." - }, - "returns": { - "_0": "Base Asset's reserve in risk fund." - } + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." }, - "owner()": { - "details": "Returns the address of the current owner." + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." }, - "pendingOwner()": { - "details": "Returns the address of the pending owner." + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." }, - "setAccessControlManager(address)": { - "custom:access": "Only Governance", - "custom:event": "Emits NewAccessControlManager event", - "details": "Admin function to set address of AccessControlManager", - "params": { - "accessControlManager_": "The new address of the AccessControlManager" - } - }, - "setConvertibleBaseAsset(address)": { - "custom:access": "Only Governance", - "custom:error": "ZeroAddressNotAllowed is thrown when convertible base asset address is zero", - "custom:event": "ConvertibleBaseAssetUpdated emit on success", - "details": "Convertible base asset setter", - "params": { - "convertibleBaseAsset_": "Address of the convertible base asset" - } - }, - "setRiskFundConverter(address)": { - "custom:access": "Only Governance", - "custom:error": "ZeroAddressNotAllowed is thrown when risk fund converter address is zero", - "custom:event": "RiskFundConverterUpdated emit on success", - "details": "Risk fund converter setter", - "params": { - "riskFundConverter_": "Address of the risk fund converter" - } - }, - "setShortfallContractAddress(address)": { - "custom:access": "Only Governance", - "custom:error": "ZeroAddressNotAllowed is thrown when shortfall contract address is zero", - "custom:event": "ShortfallContractUpdated emit on success", - "details": "Shortfall contract address setter", - "params": { - "shortfallContractAddress_": "Address of the auction contract" - } - }, - "sweepToken(address,address,uint256)": { - "custom:access": "Only Governance", - "custom:error": "ZeroAddressNotAllowed is thrown when tokenAddress/to address is zeroZeroValueNotAllowed is thrown when amount is zero", - "custom:event": "Emits SweepToken event on success", - "params": { - "amount": "Amount need to sweep for the pool", - "to": "Address to which assets will be transferred", - "tokenAddress": "Address of the asset(token)" - } - }, - "transferOwnership(address)": { - "details": "Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner." - }, - "transferReserveForAuction(address,uint256)": { - "custom:access": "Only Shortfall contract", - "custom:error": "InvalidShortfallAddress is thrown when caller is not shortfall contractInsufficientPoolReserve is thrown when pool reserve is less than the amount needed", - "custom:event": "TransferredReserveForAuction emit on success", - "details": "Transfer tokens for auction to shortfall contract", - "params": { - "amount": "Amount to be transferred to the shortfall", - "comptroller": "Comptroller of the pool" - }, - "returns": { - "_0": "Amount of tokens transferred to the shortfall" - } - }, - "updatePoolState(address,address,uint256)": { - "custom:access": "Only RiskFundConverter contract", - "custom:error": "InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract", - "custom:event": "PoolAssetsIncreased emits on success", - "details": "Update the reserve of the asset for the specific pool after transferring to risk fund", - "params": { - "amount": "Amount transferred for the pool", - "asset": "Address of the asset(token)", - "comptroller": "Comptroller address (pool)" - } + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." } }, - "title": "RiskFundV2", "version": 1 }, "userdoc": { - "errors": { - "InsufficientBalance()": [ - { - "notice": "thrown when amount entered is greater than balance" - } - ], - "InsufficientPoolReserve(address,uint256,uint256)": [ - { - "notice": "Error is thrown when pool reserve is less than the amount needed" - } - ], - "InvalidRiskFundConverter()": [ - { - "notice": "Error is thrown when updatePoolState is not called by riskFundConverter" - } - ], - "InvalidShortfallAddress()": [ - { - "notice": "Error is thrown when transferReserveForAuction is called by non shortfall address" - } - ], - "Unauthorized(address,address,string)": [ - { - "notice": "Thrown when the action is prohibited by AccessControlManager" - } - ], - "ZeroAddressNotAllowed()": [ - { - "notice": "Thrown if the supplied address is a zero address where it is not allowed" - } - ], - "ZeroValueNotAllowed()": [ - { - "notice": "Thrown if the supplied value is 0 where it is not allowed" - } - ] - }, - "events": { - "ConvertibleBaseAssetUpdated(address,address)": { - "notice": "Emitted when convertible base asset address is updated" - }, - "NewAccessControlManager(address,address)": { - "notice": "Emitted when access control manager contract address is changed" - }, - "PoolAssetsDecreased(address,address,uint256)": { - "notice": "Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens" - }, - "PoolAssetsIncreased(address,address,uint256)": { - "notice": "Emitted when pool asset states is updated with amount transferred to this contract" - }, - "RiskFundConverterUpdated(address,address)": { - "notice": "Emitted when risk fund converter address is updated" - }, - "ShortfallContractUpdated(address,address)": { - "notice": "Emitted when shortfall contract address is updated" - }, - "SweepToken(address,address,uint256)": { - "notice": "Event emitted when tokens are swept" - }, - "TransferredReserveForAuction(address,uint256)": { - "notice": "Emitted when reserves are transferred for auction" - } - }, "kind": "user", - "methods": { - "accessControlManager()": { - "notice": "Returns the address of the access control manager contract" - }, - "convertibleBaseAsset()": { - "notice": "Address of base asset" - }, - "getPoolsBaseAssetReserves(address)": { - "notice": "Get the Amount of the Base asset in the risk fund for the specific pool." - }, - "maxLoopsLimit()": { - "notice": "Limit for the loops to avoid the DOSThis state is deprecated, using it to prevent storage collision" - }, - "poolAssetsFunds(address,address)": { - "notice": "Available asset's fund per pool in RiskFund Comptroller(pool) -> Asset -> amount" - }, - "riskFundConverter()": { - "notice": "Risk fund converter address" - }, - "setAccessControlManager(address)": { - "notice": "Sets the address of AccessControlManager" - }, - "shortfall()": { - "notice": "Address of shortfall contract" - }, - "sweepToken(address,address,uint256)": { - "notice": "Function to sweep baseAsset for pool, Tokens are sent to address(to)" - } - }, - "notice": "Contract with basic features to hold base asset for different Comptrollers", + "methods": {}, "version": 1 }, "storageLayout": { - "storage": [ - { - "astId": 244, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 247, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 1478, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 116, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 236, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 25, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_pendingOwner", - "offset": 0, - "slot": "101", - "type": "t_address" - }, - { - "astId": 104, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 4921, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_accessControlManager", - "offset": 0, - "slot": "151", - "type": "t_contract(IAccessControlManagerV8)5106" - }, - { - "astId": 4926, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 7563, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__deprecatedSlot1", - "offset": 0, - "slot": "201", - "type": "t_bytes32" - }, - { - "astId": 7570, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "poolAssetsFunds", - "offset": 0, - "slot": "202", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 7573, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__deprecatedSlot2", - "offset": 0, - "slot": "203", - "type": "t_bytes32" - }, - { - "astId": 7576, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__deprecatedSlot3", - "offset": 0, - "slot": "204", - "type": "t_bytes32" - }, - { - "astId": 7581, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "205", - "type": "t_array(t_uint256)46_storage" - }, - { - "astId": 7586, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "maxLoopsLimit", - "offset": 0, - "slot": "251", - "type": "t_uint256" - }, - { - "astId": 7591, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "252", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 7600, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "convertibleBaseAsset", - "offset": 0, - "slot": "301", - "type": "t_address" - }, - { - "astId": 7603, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "shortfall", - "offset": 0, - "slot": "302", - "type": "t_address" - }, - { - "astId": 7606, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "pancakeSwapRouter", - "offset": 0, - "slot": "303", - "type": "t_address" - }, - { - "astId": 7609, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "minAmountToConvert", - "offset": 0, - "slot": "304", - "type": "t_uint256" - }, - { - "astId": 547, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "_status", - "offset": 0, - "slot": "305", - "type": "t_uint256" - }, - { - "astId": 616, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "__gap", - "offset": 0, - "slot": "306", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 7618, - "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", - "label": "riskFundConverter", - "offset": 0, - "slot": "355", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)46_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[46]", - "numberOfBytes": "1472" - }, - "t_array(t_uint256)49_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(IAccessControlManagerV8)5106": { - "encoding": "inplace", - "label": "contract IAccessControlManagerV8", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } + "storage": [], + "types": null } } diff --git a/deployments/bsctestnet/RiskFundV2_Implementation.json b/deployments/bsctestnet/RiskFundV2_Implementation.json new file mode 100644 index 00000000..f0e63bde --- /dev/null +++ b/deployments/bsctestnet/RiskFundV2_Implementation.json @@ -0,0 +1,1049 @@ +{ + "address": "0xcA2A023FBe3be30b7187E88D7FDE1A9a4358B509", + "abi": [ + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "poolReserve", + "type": "uint256" + } + ], + "name": "InsufficientPoolReserve", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRiskFundConverter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortfallAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldConvertibleBaseAsset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newConvertibleBaseAsset", + "type": "address" + } + ], + "name": "ConvertibleBaseAssetUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "PoolAssetsDecreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "PoolAssetsIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldRiskFundConverter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newRiskFundConverter", + "type": "address" + } + ], + "name": "RiskFundConverterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldShortfallContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newShortfallContract", + "type": "address" + } + ], + "name": "ShortfallContractUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferredReserveForAuction", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "convertibleBaseAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolsBaseAssetReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "poolAssetsFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "riskFundConverter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "convertibleBaseAsset_", + "type": "address" + } + ], + "name": "setConvertibleBaseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "riskFundConverter_", + "type": "address" + } + ], + "name": "setRiskFundConverter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "shortfallContractAddress_", + "type": "address" + } + ], + "name": "setShortfallContractAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferReserveForAuction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "updatePoolState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xe099e07b1b29bbec08be51fdd4ba175e5c2be6b14f6ae5c47bea363149d735cd", + "receipt": { + "to": null, + "from": "0x02EB950C215D12d723b44a18CfF098C6E166C531", + "contractAddress": "0xcA2A023FBe3be30b7187E88D7FDE1A9a4358B509", + "transactionIndex": 0, + "gasUsed": "1345902", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x719459c15feafb725beb928a8991f96cd52c5049a7e6be1bd4b3137521a8bd79", + "transactionHash": "0xe099e07b1b29bbec08be51fdd4ba175e5c2be6b14f6ae5c47bea363149d735cd", + "logs": [], + "blockNumber": 36750922, + "cumulativeGasUsed": "1345902", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "ee8827a99e03cdf6f6a94fb8782ddf44", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"poolReserve\",\"type\":\"uint256\"}],\"name\":\"InsufficientPoolReserve\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRiskFundConverter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortfallAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsDecreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"PoolAssetsIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldRiskFundConverter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newRiskFundConverter\",\"type\":\"address\"}],\"name\":\"RiskFundConverterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newShortfallContract\",\"type\":\"address\"}],\"name\":\"ShortfallContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLoopsLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"poolAssetsFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"riskFundConverter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"riskFundConverter_\",\"type\":\"address\"}],\"name\":\"setRiskFundConverter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"updatePoolState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"custom:security-contact\":\"https://github.com/VenusProtocol/protocol-reserve#discussion\",\"details\":\"This contract does not support BNB\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"custom:event\":\"ConvertibleBaseAssetUpdated emit on success\",\"details\":\"Convertible base asset setter\",\"params\":{\"convertibleBaseAsset_\":\"Address of the convertible base asset\"}},\"setRiskFundConverter(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when risk fund converter address is zero\",\"custom:event\":\"RiskFundConverterUpdated emit on success\",\"details\":\"Risk fund converter setter\",\"params\":{\"riskFundConverter_\":\"Address of the risk fund converter\"}},\"setShortfallContractAddress(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"custom:event\":\"ShortfallContractUpdated emit on success\",\"details\":\"Shortfall contract address setter\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"sweepToken(address,address,uint256)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when tokenAddress/to address is zeroZeroValueNotAllowed is thrown when amount is zero\",\"custom:event\":\"Emits SweepToken event on success\",\"params\":{\"amount\":\"Amount need to sweep for the pool\",\"to\":\"Address to which assets will be transferred\",\"tokenAddress\":\"Address of the asset(token)\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"transferReserveForAuction(address,uint256)\":{\"custom:access\":\"Only Shortfall contract\",\"custom:error\":\"InvalidShortfallAddress is thrown when caller is not shortfall contractInsufficientPoolReserve is thrown when pool reserve is less than the amount needed\",\"custom:event\":\"TransferredReserveForAuction emit on success\",\"details\":\"Transfer tokens for auction to shortfall contract\",\"params\":{\"amount\":\"Amount to be transferred to the shortfall\",\"comptroller\":\"Comptroller of the pool\"},\"returns\":{\"_0\":\"Amount of tokens transferred to the shortfall\"}},\"updatePoolState(address,address,uint256)\":{\"custom:access\":\"Only RiskFundConverter contract\",\"custom:error\":\"InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\",\"custom:event\":\"PoolAssetsIncreased emits on success\",\"details\":\"Update the reserve of the asset for the specific pool after transferring to risk fund\",\"params\":{\"amount\":\"Amount transferred for the pool\",\"asset\":\"Address of the asset(token)\",\"comptroller\":\"Comptroller address (pool)\"}}},\"title\":\"RiskFundV2\",\"version\":1},\"userdoc\":{\"errors\":{\"InsufficientBalance()\":[{\"notice\":\"thrown when amount entered is greater than balance\"}],\"InsufficientPoolReserve(address,uint256,uint256)\":[{\"notice\":\"Error is thrown when pool reserve is less than the amount needed\"}],\"InvalidRiskFundConverter()\":[{\"notice\":\"Error is thrown when updatePoolState is not called by riskFundConverter\"}],\"InvalidShortfallAddress()\":[{\"notice\":\"Error is thrown when transferReserveForAuction is called by non shortfall address\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset address is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolAssetsDecreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\"},\"PoolAssetsIncreased(address,address,uint256)\":{\"notice\":\"Emitted when pool asset states is updated with amount transferred to this contract\"},\"RiskFundConverterUpdated(address,address)\":{\"notice\":\"Emitted when risk fund converter address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"Event emitted when tokens are swept\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"convertibleBaseAsset()\":{\"notice\":\"Address of base asset\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"maxLoopsLimit()\":{\"notice\":\"Limit for the loops to avoid the DOSThis state is deprecated, using it to prevent storage collision\"},\"poolAssetsFunds(address,address)\":{\"notice\":\"Available asset's fund per pool in RiskFund Comptroller(pool) -> Asset -> amount\"},\"riskFundConverter()\":{\"notice\":\"Risk fund converter address\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"shortfall()\":{\"notice\":\"Address of shortfall contract\"},\"sweepToken(address,address,uint256)\":{\"notice\":\"Function to sweep baseAsset for pool, Tokens are sent to address(to)\"}},\"notice\":\"Contract with basic features to hold base asset for different Comptrollers\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ProtocolReserve/RiskFundV2.sol\":\"RiskFundV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides 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} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 IERC20Upgradeable {\\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(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\nimport \\\"./IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title AccessControlledV8\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\\n /// @notice Access control manager contract\\n IAccessControlManagerV8 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /// @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Sets the address of AccessControlManager\\n * @dev Admin function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n * @custom:event Emits NewAccessControlManager event\\n * @custom:access Only Governance\\n */\\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\\n _setAccessControlManager(accessControlManager_);\\n }\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV8) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b805a5d09990e2c4f7839afe7726a02f8452261eb3d0d488e24129ec0a7736d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8adbe291d659987faf4de606736227ad9d8e1a0e284a33a6ca12b30ab2a504b2\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xd55726634a83a862a9cef9d34c41694d3d0fea86cdbc57d6674af066792194b1\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFund.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IRiskFund\\n * @author Venus\\n * @notice Interface implemented by `RiskFund`.\\n */\\ninterface IRiskFund {\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external;\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\\n/**\\n * @title IRiskFundGetters\\n * @author Venus\\n * @notice Interface implemented by `RiskFund` for getter methods.\\n */\\ninterface IRiskFundGetters {\\n function convertibleBaseAsset() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5f2a65443264433c222053b317aa489aad17311f8d5def1975221073176dbc0f\",\"license\":\"BSD-3-Clause\"},\"contracts/Interfaces/IRiskFundConverter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\ninterface IRiskFundConverter {\\n function updateAssetsState(address comptroller, address asset) external;\\n\\n function getPools(address asset) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0xb7335d0d343100ca6294c5858193f52462d1818212ff4435c14da961af87a39e\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ReentrancyGuardUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\n\\n/// @title ReserveHelpersStorage\\n/// @author Venus\\n/// @dev Reserve helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract ReserveHelpersStorage is Ownable2StepUpgradeable {\\n /// @notice Deprecated slot for assetReserves mapping\\n bytes32 private __deprecatedSlot1;\\n\\n /// @notice Available asset's fund per pool in RiskFund\\n /// Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) public poolAssetsFunds;\\n\\n /// @notice Deprecated slot for poolRegistry address\\n bytes32 private __deprecatedSlot2;\\n /// @notice Deprecated slot for status variable\\n bytes32 private __deprecatedSlot3;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n uint256[46] private __gap;\\n}\\n\\n/// @title MaxLoopsLimitHelpersStorage\\n/// @author Venus\\n/// @dev Max loop limit helpers storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract MaxLoopsLimitHelpersStorage {\\n /// @notice Limit for the loops to avoid the DOS\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 public maxLoopsLimit;\\n\\n /// @dev This empty reserved space is put in place to allow future versions to add new\\n /// variables without shifting down storage in the inheritance chain.\\n /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n uint256[49] private __gap;\\n}\\n\\n/// @title RiskFundV1Storage\\n/// @author Venus\\n/// @dev Risk fund V1 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV1Storage is ReserveHelpersStorage, MaxLoopsLimitHelpersStorage {\\n /// @notice Address of base asset\\n address public convertibleBaseAsset;\\n /// @notice Address of shortfall contract\\n address public shortfall;\\n\\n /// @notice This state is deprecated, using it to prevent storage collision\\n address private pancakeSwapRouter;\\n /// @notice This state is deprecated, using it to prevent storage collision\\n uint256 private minAmountToConvert;\\n}\\n\\n/// @title RiskFundV2Storage\\n/// @author Venus\\n/// @dev Risk fund V2 storage\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2Storage is RiskFundV1Storage, ReentrancyGuardUpgradeable {\\n /// @notice Risk fund converter address\\n address public riskFundConverter;\\n}\\n\",\"keccak256\":\"0x0620187dca927191ab256ea20e42416883380690e54ba344807867adba01d7fb\",\"license\":\"BSD-3-Clause\"},\"contracts/ProtocolReserve/RiskFundV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\n\\nimport { IRiskFund } from \\\"../Interfaces/IRiskFund.sol\\\";\\nimport { IRiskFundConverter } from \\\"../Interfaces/IRiskFundConverter.sol\\\";\\nimport { RiskFundV2Storage } from \\\"./RiskFundStorage.sol\\\";\\n\\n/// @title RiskFundV2\\n/// @author Venus\\n/// @notice Contract with basic features to hold base asset for different Comptrollers\\n/// @dev This contract does not support BNB\\n/// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion\\ncontract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice Emitted when convertible base asset address is updated\\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\\n\\n /// @notice Emitted when risk fund converter address is updated\\n event RiskFundConverterUpdated(address indexed oldRiskFundConverter, address indexed newRiskFundConverter);\\n\\n /// @notice Emitted when shortfall contract address is updated\\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\\n\\n /// @notice Emitted when reserves are transferred for auction\\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred to this contract\\n event PoolAssetsIncreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens\\n event PoolAssetsDecreased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Event emitted when tokens are swept\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /// @notice Error is thrown when updatePoolState is not called by riskFundConverter\\n error InvalidRiskFundConverter();\\n\\n /// @notice Error is thrown when transferReserveForAuction is called by non shortfall address\\n error InvalidShortfallAddress();\\n\\n /// @notice thrown when amount entered is greater than balance\\n error InsufficientBalance();\\n\\n /// @notice Error is thrown when pool reserve is less than the amount needed\\n error InsufficientPoolReserve(address comptroller, uint256 amount, uint256 poolReserve);\\n\\n /// @dev Convertible base asset setter\\n /// @param convertibleBaseAsset_ Address of the convertible base asset\\n /// @custom:event ConvertibleBaseAssetUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\\n /// @custom:access Only Governance\\n function setConvertibleBaseAsset(address convertibleBaseAsset_) external onlyOwner {\\n ensureNonzeroAddress(convertibleBaseAsset_);\\n emit ConvertibleBaseAssetUpdated(convertibleBaseAsset, convertibleBaseAsset_);\\n convertibleBaseAsset = convertibleBaseAsset_;\\n }\\n\\n /// @dev Risk fund converter setter\\n /// @param riskFundConverter_ Address of the risk fund converter\\n /// @custom:event RiskFundConverterUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when risk fund converter address is zero\\n /// @custom:access Only Governance\\n function setRiskFundConverter(address riskFundConverter_) external onlyOwner {\\n ensureNonzeroAddress(riskFundConverter_);\\n emit RiskFundConverterUpdated(riskFundConverter, riskFundConverter_);\\n riskFundConverter = riskFundConverter_;\\n }\\n\\n /// @dev Shortfall contract address setter\\n /// @param shortfallContractAddress_ Address of the auction contract\\n /// @custom:event ShortfallContractUpdated emit on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n /// @custom:access Only Governance\\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\\n ensureNonzeroAddress(shortfallContractAddress_);\\n emit ShortfallContractUpdated(shortfall, shortfallContractAddress_);\\n shortfall = shortfallContractAddress_;\\n }\\n\\n /// @dev Transfer tokens for auction to shortfall contract\\n /// @param comptroller Comptroller of the pool\\n /// @param amount Amount to be transferred to the shortfall\\n /// @return Amount of tokens transferred to the shortfall\\n /// @custom:event TransferredReserveForAuction emit on success\\n /// @custom:error InvalidShortfallAddress is thrown when caller is not shortfall contract\\n /// @custom:error InsufficientPoolReserve is thrown when pool reserve is less than the amount needed\\n /// @custom:access Only Shortfall contract\\n function transferReserveForAuction(address comptroller, uint256 amount)\\n external\\n override\\n nonReentrant\\n returns (uint256)\\n {\\n uint256 poolReserve = poolAssetsFunds[comptroller][convertibleBaseAsset];\\n\\n if (msg.sender != shortfall) {\\n revert InvalidShortfallAddress();\\n }\\n if (amount > poolReserve) {\\n revert InsufficientPoolReserve(comptroller, amount, poolReserve);\\n }\\n\\n unchecked {\\n poolAssetsFunds[comptroller][convertibleBaseAsset] = poolReserve - amount;\\n }\\n\\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall, amount);\\n emit TransferredReserveForAuction(comptroller, amount);\\n\\n return amount;\\n }\\n\\n /// @notice Function to sweep baseAsset for pool, Tokens are sent to address(to)\\n /// @param tokenAddress Address of the asset(token)\\n /// @param to Address to which assets will be transferred\\n /// @param amount Amount need to sweep for the pool\\n /// @custom:event Emits SweepToken event on success\\n /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero\\n /// @custom:error ZeroValueNotAllowed is thrown when amount is zero\\n /// @custom:access Only Governance\\n function sweepToken(\\n address tokenAddress,\\n address to,\\n uint256 amount\\n ) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(tokenAddress);\\n ensureNonzeroAddress(to);\\n ensureNonzeroValue(amount);\\n\\n IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);\\n preSweepToken(tokenAddress, amount);\\n token.safeTransfer(to, amount);\\n\\n emit SweepToken(tokenAddress, to, amount);\\n }\\n\\n /**\\n * @notice Get the Amount of the Base asset in the risk fund for the specific pool.\\n * @param comptroller Comptroller address(pool).\\n * @return Base Asset's reserve in risk fund.\\n */\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256) {\\n return poolAssetsFunds[comptroller][convertibleBaseAsset];\\n }\\n\\n /// @dev Update the reserve of the asset for the specific pool after transferring to risk fund\\n /// @param comptroller Comptroller address (pool)\\n /// @param asset Address of the asset(token)\\n /// @param amount Amount transferred for the pool\\n /// @custom:event PoolAssetsIncreased emits on success\\n /// @custom:error InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract\\n /// @custom:access Only RiskFundConverter contract\\n function updatePoolState(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) public {\\n if (msg.sender != riskFundConverter) {\\n revert InvalidRiskFundConverter();\\n }\\n\\n poolAssetsFunds[comptroller][asset] += amount;\\n emit PoolAssetsIncreased(comptroller, asset, amount);\\n }\\n\\n /// @dev Operations to perform before sweeping tokens\\n /// @param tokenAddress Address of the token\\n /// @param amount Amount transferred to address(to)\\n /// @custom:error InsufficientBalance is thrown when amount entered is greater than balance\\n function preSweepToken(address tokenAddress, uint256 amount) internal {\\n uint256 balance = IERC20Upgradeable(tokenAddress).balanceOf(address(this));\\n if (amount > balance) revert InsufficientBalance();\\n\\n address[] memory pools = IRiskFundConverter(riskFundConverter).getPools(tokenAddress);\\n\\n uint256 assetReserves;\\n uint256 poolsLength = pools.length;\\n for (uint256 i; i < poolsLength; ) {\\n assetReserves += poolAssetsFunds[pools[i]][tokenAddress];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256 balanceDiff = balance - assetReserves;\\n\\n if (balanceDiff < amount) {\\n uint256 amountDiff;\\n unchecked {\\n amountDiff = amount - balanceDiff;\\n }\\n uint256 distributedShare;\\n for (uint256 i; i < poolsLength; ) {\\n if (poolAssetsFunds[pools[i]][tokenAddress] != 0) {\\n uint256 poolAmountShare;\\n if (i < (poolsLength - 1)) {\\n poolAmountShare = (poolAssetsFunds[pools[i]][tokenAddress] * amount) / assetReserves;\\n distributedShare += poolAmountShare;\\n } else {\\n poolAmountShare = amountDiff - distributedShare;\\n }\\n poolAssetsFunds[pools[i]][tokenAddress] -= poolAmountShare;\\n emit PoolAssetsDecreased(pools[i], tokenAddress, poolAmountShare);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe79f3802602fe5b406a3c374360009eb92e9545aee1ac833916af6c749979a0e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061178c806100206000396000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063715018a6116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102d1578063e30c3978146102e5578063f2fde38b146102f657600080fd5b8063b4a0bdf3146102b7578063be26317e146102c857600080fd5b806379ba5097116100b257806379ba5097146102635780638da5cb5b1461026b578063a69bd19e1461027c57600080fd5b8063715018a61461024857806377d4937f1461025057600080fd5b80632eef9172116101245780635dbe3533116101095780635dbe3533146101f7578063601bb5a91461022257806364aff9ec1461023557600080fd5b80632eef9172146101d057806353ac3537146101e457600080fd5b80630a9837c5146101565780630e32cb861461017c57806319b1faef146101915780632e688141146101bd575b600080fd5b61016961016436600461138d565b610309565b6040519081526020015b60405180910390f35b61018f61018a3660046113b9565b610468565b005b61012e546101a5906001600160a01b031681565b6040516001600160a01b039091168152602001610173565b61018f6101cb3660046113b9565b61047c565b610163546101a5906001600160a01b031681565b61018f6101f23660046113dd565b610503565b61016961020536600461141e565b60ca60209081526000928352604080842090915290825290205481565b61018f6102303660046113b9565b6105d8565b61018f6102433660046113dd565b61065f565b61018f610707565b61018f61025e3660046113b9565b61071b565b61018f6107a2565b6033546001600160a01b03166101a5565b61016961028a3660046113b9565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101a5565b61016960fb5481565b61012d546101a5906001600160a01b031681565b6065546001600160a01b03166101a5565b61018f6103043660046113b9565b610847565b60006103136108d0565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e54909116331461037c576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808311156103d4576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461041892908116911685610945565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161045391815260200190565b60405180910390a25050600161013155919050565b6104706109c5565b61047981610a39565b50565b6104846109c5565b61048d81610b48565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610548576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca602090815260408083209386168352929052908120805483929061057f908490611486565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105cb91815260200190565b60405180910390a3505050565b6105e06109c5565b6105e981610b48565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6106676109c5565b61066f6108d0565b61067883610b48565b61068182610b48565b61068a81610b88565b826106958183610bc2565b6106a96001600160a01b0382168484610945565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516106ee91815260200190565b60405180910390a350610702600161013155565b505050565b61070f6109c5565b6107196000610fe6565b565b6107236109c5565b61072c81610b48565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461083e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103cb565b61047981610fe6565b61084f6109c5565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556108986033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002610131540361093d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103cb565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610702908490611017565b6033546001600160a01b03163314610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103cb565b6001600160a01b038116610acf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103cb565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b038116610479576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003610479576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610c22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c46919061149e565b905080821115610c82576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610ce7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610d2d91908101906114f6565b8051909150600090815b81811015610db65760ca6000858381518110610d5557610d556115d9565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610dac9190611486565b9250600101610d37565b506000610dc38386611608565b905085811015610fdd578086036000805b84811015610fd95760ca6000888381518110610df257610df26115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014610fd1576000610e52600187611608565b821015610ee457868a60ca60008b8681518110610e7157610e716115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054610ec7919061161f565b610ed1919061165c565b9050610edd8184611486565b9250610ef1565b610eee8385611608565b90505b8060ca60008a8581518110610f0857610f086115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b031681526020019081526020016000206000828254610f629190611608565b925050819055508a6001600160a01b0316888381518110610f8557610f856115d9565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd8432083604051610fc791815260200190565b60405180910390a3505b600101610dd4565b5050505b50505050505050565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561047981611119565b600061106c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111839092919063ffffffff16565b905080516000148061108d57508080602001905181019061108d9190611697565b610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103cb565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060611192848460008561119a565b949350505050565b60608247101561122c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103cb565b600080866001600160a01b0316858760405161124891906116e9565b60006040518083038185875af1925050503d8060008114611285576040519150601f19603f3d011682016040523d82523d6000602084013e61128a565b606091505b509150915061129b878383876112a6565b979650505050505050565b6060831561132f578251600003611328576001600160a01b0385163b611328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103cb565b5081611192565b61119283838151156113445781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103cb9190611705565b6001600160a01b038116811461047957600080fd5b600080604083850312156113a057600080fd5b82356113ab81611378565b946020939093013593505050565b6000602082840312156113cb57600080fd5b81356113d681611378565b9392505050565b6000806000606084860312156113f257600080fd5b83356113fd81611378565b9250602084013561140d81611378565b929592945050506040919091013590565b6000806040838503121561143157600080fd5b823561143c81611378565b9150602083013561144c81611378565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561149957611499611457565b500190565b6000602082840312156114b057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80516114f181611378565b919050565b6000602080838503121561150957600080fd5b825167ffffffffffffffff8082111561152157600080fd5b818501915085601f83011261153557600080fd5b815181811115611547576115476114b7565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561158a5761158a6114b7565b6040529182528482019250838101850191888311156115a857600080fd5b938501935b828510156115cd576115be856114e6565b845293850193928501926115ad565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008282101561161a5761161a611457565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561165757611657611457565b500290565b600082611692577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156116a957600080fd5b815180151581146113d657600080fd5b60005b838110156116d45781810151838201526020016116bc565b838111156116e3576000848401525b50505050565b600082516116fb8184602087016116b9565b9190910192915050565b60208152600082518060208401526117248160408501602087016116b9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea26469706673582212209c38201c74c3ca466d0abbc6a00c9bd8bb8ed5a5a063d3202f59106f43fcc5a764736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063715018a6116100cd578063b4a0bdf311610081578063c8ecc0d311610066578063c8ecc0d3146102d1578063e30c3978146102e5578063f2fde38b146102f657600080fd5b8063b4a0bdf3146102b7578063be26317e146102c857600080fd5b806379ba5097116100b257806379ba5097146102635780638da5cb5b1461026b578063a69bd19e1461027c57600080fd5b8063715018a61461024857806377d4937f1461025057600080fd5b80632eef9172116101245780635dbe3533116101095780635dbe3533146101f7578063601bb5a91461022257806364aff9ec1461023557600080fd5b80632eef9172146101d057806353ac3537146101e457600080fd5b80630a9837c5146101565780630e32cb861461017c57806319b1faef146101915780632e688141146101bd575b600080fd5b61016961016436600461138d565b610309565b6040519081526020015b60405180910390f35b61018f61018a3660046113b9565b610468565b005b61012e546101a5906001600160a01b031681565b6040516001600160a01b039091168152602001610173565b61018f6101cb3660046113b9565b61047c565b610163546101a5906001600160a01b031681565b61018f6101f23660046113dd565b610503565b61016961020536600461141e565b60ca60209081526000928352604080842090915290825290205481565b61018f6102303660046113b9565b6105d8565b61018f6102433660046113dd565b61065f565b61018f610707565b61018f61025e3660046113b9565b61071b565b61018f6107a2565b6033546001600160a01b03166101a5565b61016961028a3660046113b9565b6001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6097546001600160a01b03166101a5565b61016960fb5481565b61012d546101a5906001600160a01b031681565b6065546001600160a01b03166101a5565b61018f6103043660046113b9565b610847565b60006103136108d0565b6001600160a01b03838116600090815260ca6020908152604080832061012d548516845290915290205461012e54909116331461037c576040517fe7792c3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808311156103d4576040517f5f1b50b80000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260248101849052604481018290526064015b60405180910390fd5b6001600160a01b03808516600090815260ca6020908152604080832061012d8054861685529252909120858403905561012e54905461041892908116911685610945565b836001600160a01b03167fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd8460405161045391815260200190565b60405180910390a25050600161013155919050565b6104706109c5565b61047981610a39565b50565b6104846109c5565b61048d81610b48565b61012d546040516001600160a01b038084169216907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a361012d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610163546001600160a01b03163314610548576040517fece95bc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03808416600090815260ca602090815260408083209386168352929052908120805483929061057f908490611486565b92505081905550816001600160a01b0316836001600160a01b03167f17452316fd883c456b01c6722a103031ccd3cf17a1dabdbf96cd1109652d6110836040516105cb91815260200190565b60405180910390a3505050565b6105e06109c5565b6105e981610b48565b610163546040516001600160a01b038084169216907f49ca267ed5631dd7b16589efad418137b8fb106674777fc37d2cb82e853dbd2790600090a361016380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6106676109c5565b61066f6108d0565b61067883610b48565b61068182610b48565b61068a81610b88565b826106958183610bc2565b6106a96001600160a01b0382168484610945565b826001600160a01b0316846001600160a01b03167f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5846040516106ee91815260200190565b60405180910390a350610702600161013155565b505050565b61070f6109c5565b6107196000610fe6565b565b6107236109c5565b61072c81610b48565b61012e546040516001600160a01b038084169216907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a361012e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60655433906001600160a01b0316811461083e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016103cb565b61047981610fe6565b61084f6109c5565b606580546001600160a01b0383167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556108986033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6002610131540361093d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103cb565b600261013155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610702908490611017565b6033546001600160a01b03163314610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103cb565b6001600160a01b038116610acf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e6167657220616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103cb565b609780546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0910160405180910390a15050565b6001600160a01b038116610479576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003610479576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610c22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c46919061149e565b905080821115610c82576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610163546040517f5c39f4670000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526000921690635c39f46790602401600060405180830381865afa158015610ce7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610d2d91908101906114f6565b8051909150600090815b81811015610db65760ca6000858381518110610d5557610d556115d9565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000205483610dac9190611486565b9250600101610d37565b506000610dc38386611608565b905085811015610fdd578086036000805b84811015610fd95760ca6000888381518110610df257610df26115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002054600014610fd1576000610e52600187611608565b821015610ee457868a60ca60008b8681518110610e7157610e716115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b0316815260200190815260200160002054610ec7919061161f565b610ed1919061165c565b9050610edd8184611486565b9250610ef1565b610eee8385611608565b90505b8060ca60008a8581518110610f0857610f086115d9565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b031681526020019081526020016000206000828254610f629190611608565b925050819055508a6001600160a01b0316888381518110610f8557610f856115d9565b60200260200101516001600160a01b03167fdfbd88fdb255ea04a0084e45259969bdf724b3fbd610a114da4a0dd51bd8432083604051610fc791815260200190565b60405180910390a3505b600101610dd4565b5050505b50505050505050565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561047981611119565b600061106c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111839092919063ffffffff16565b905080516000148061108d57508080602001905181019061108d9190611697565b610702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103cb565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060611192848460008561119a565b949350505050565b60608247101561122c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103cb565b600080866001600160a01b0316858760405161124891906116e9565b60006040518083038185875af1925050503d8060008114611285576040519150601f19603f3d011682016040523d82523d6000602084013e61128a565b606091505b509150915061129b878383876112a6565b979650505050505050565b6060831561132f578251600003611328576001600160a01b0385163b611328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103cb565b5081611192565b61119283838151156113445781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103cb9190611705565b6001600160a01b038116811461047957600080fd5b600080604083850312156113a057600080fd5b82356113ab81611378565b946020939093013593505050565b6000602082840312156113cb57600080fd5b81356113d681611378565b9392505050565b6000806000606084860312156113f257600080fd5b83356113fd81611378565b9250602084013561140d81611378565b929592945050506040919091013590565b6000806040838503121561143157600080fd5b823561143c81611378565b9150602083013561144c81611378565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561149957611499611457565b500190565b6000602082840312156114b057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80516114f181611378565b919050565b6000602080838503121561150957600080fd5b825167ffffffffffffffff8082111561152157600080fd5b818501915085601f83011261153557600080fd5b815181811115611547576115476114b7565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561158a5761158a6114b7565b6040529182528482019250838101850191888311156115a857600080fd5b938501935b828510156115cd576115be856114e6565b845293850193928501926115ad565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008282101561161a5761161a611457565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561165757611657611457565b500290565b600082611692577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156116a957600080fd5b815180151581146113d657600080fd5b60005b838110156116d45781810151838201526020016116bc565b838111156116e3576000848401525b50505050565b600082516116fb8184602087016116b9565b9190910192915050565b60208152600082518060208401526117248160408501602087016116b9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea26469706673582212209c38201c74c3ca466d0abbc6a00c9bd8bb8ed5a5a063d3202f59106f43fcc5a764736f6c634300080d0033", + "devdoc": { + "author": "Venus", + "custom:security-contact": "https://github.com/VenusProtocol/protocol-reserve#discussion", + "details": "This contract does not support BNB", + "kind": "dev", + "methods": { + "acceptOwnership()": { + "details": "The new owner accepts the ownership transfer." + }, + "getPoolsBaseAssetReserves(address)": { + "params": { + "comptroller": "Comptroller address(pool)." + }, + "returns": { + "_0": "Base Asset's reserve in risk fund." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pendingOwner()": { + "details": "Returns the address of the pending owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setAccessControlManager(address)": { + "custom:access": "Only Governance", + "custom:event": "Emits NewAccessControlManager event", + "details": "Admin function to set address of AccessControlManager", + "params": { + "accessControlManager_": "The new address of the AccessControlManager" + } + }, + "setConvertibleBaseAsset(address)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when convertible base asset address is zero", + "custom:event": "ConvertibleBaseAssetUpdated emit on success", + "details": "Convertible base asset setter", + "params": { + "convertibleBaseAsset_": "Address of the convertible base asset" + } + }, + "setRiskFundConverter(address)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when risk fund converter address is zero", + "custom:event": "RiskFundConverterUpdated emit on success", + "details": "Risk fund converter setter", + "params": { + "riskFundConverter_": "Address of the risk fund converter" + } + }, + "setShortfallContractAddress(address)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when shortfall contract address is zero", + "custom:event": "ShortfallContractUpdated emit on success", + "details": "Shortfall contract address setter", + "params": { + "shortfallContractAddress_": "Address of the auction contract" + } + }, + "sweepToken(address,address,uint256)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when tokenAddress/to address is zeroZeroValueNotAllowed is thrown when amount is zero", + "custom:event": "Emits SweepToken event on success", + "params": { + "amount": "Amount need to sweep for the pool", + "to": "Address to which assets will be transferred", + "tokenAddress": "Address of the asset(token)" + } + }, + "transferOwnership(address)": { + "details": "Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner." + }, + "transferReserveForAuction(address,uint256)": { + "custom:access": "Only Shortfall contract", + "custom:error": "InvalidShortfallAddress is thrown when caller is not shortfall contractInsufficientPoolReserve is thrown when pool reserve is less than the amount needed", + "custom:event": "TransferredReserveForAuction emit on success", + "details": "Transfer tokens for auction to shortfall contract", + "params": { + "amount": "Amount to be transferred to the shortfall", + "comptroller": "Comptroller of the pool" + }, + "returns": { + "_0": "Amount of tokens transferred to the shortfall" + } + }, + "updatePoolState(address,address,uint256)": { + "custom:access": "Only RiskFundConverter contract", + "custom:error": "InvalidRiskFundConverter is thrown if caller is not riskFundConverter contract", + "custom:event": "PoolAssetsIncreased emits on success", + "details": "Update the reserve of the asset for the specific pool after transferring to risk fund", + "params": { + "amount": "Amount transferred for the pool", + "asset": "Address of the asset(token)", + "comptroller": "Comptroller address (pool)" + } + } + }, + "title": "RiskFundV2", + "version": 1 + }, + "userdoc": { + "errors": { + "InsufficientBalance()": [ + { + "notice": "thrown when amount entered is greater than balance" + } + ], + "InsufficientPoolReserve(address,uint256,uint256)": [ + { + "notice": "Error is thrown when pool reserve is less than the amount needed" + } + ], + "InvalidRiskFundConverter()": [ + { + "notice": "Error is thrown when updatePoolState is not called by riskFundConverter" + } + ], + "InvalidShortfallAddress()": [ + { + "notice": "Error is thrown when transferReserveForAuction is called by non shortfall address" + } + ], + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ], + "ZeroAddressNotAllowed()": [ + { + "notice": "Thrown if the supplied address is a zero address where it is not allowed" + } + ], + "ZeroValueNotAllowed()": [ + { + "notice": "Thrown if the supplied value is 0 where it is not allowed" + } + ] + }, + "events": { + "ConvertibleBaseAssetUpdated(address,address)": { + "notice": "Emitted when convertible base asset address is updated" + }, + "NewAccessControlManager(address,address)": { + "notice": "Emitted when access control manager contract address is changed" + }, + "PoolAssetsDecreased(address,address,uint256)": { + "notice": "Emitted when pool asset states is updated with amount transferred from this contract on sweeping tokens" + }, + "PoolAssetsIncreased(address,address,uint256)": { + "notice": "Emitted when pool asset states is updated with amount transferred to this contract" + }, + "RiskFundConverterUpdated(address,address)": { + "notice": "Emitted when risk fund converter address is updated" + }, + "ShortfallContractUpdated(address,address)": { + "notice": "Emitted when shortfall contract address is updated" + }, + "SweepToken(address,address,uint256)": { + "notice": "Event emitted when tokens are swept" + }, + "TransferredReserveForAuction(address,uint256)": { + "notice": "Emitted when reserves are transferred for auction" + } + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "Returns the address of the access control manager contract" + }, + "convertibleBaseAsset()": { + "notice": "Address of base asset" + }, + "getPoolsBaseAssetReserves(address)": { + "notice": "Get the Amount of the Base asset in the risk fund for the specific pool." + }, + "maxLoopsLimit()": { + "notice": "Limit for the loops to avoid the DOSThis state is deprecated, using it to prevent storage collision" + }, + "poolAssetsFunds(address,address)": { + "notice": "Available asset's fund per pool in RiskFund Comptroller(pool) -> Asset -> amount" + }, + "riskFundConverter()": { + "notice": "Risk fund converter address" + }, + "setAccessControlManager(address)": { + "notice": "Sets the address of AccessControlManager" + }, + "shortfall()": { + "notice": "Address of shortfall contract" + }, + "sweepToken(address,address,uint256)": { + "notice": "Function to sweep baseAsset for pool, Tokens are sent to address(to)" + } + }, + "notice": "Contract with basic features to hold base asset for different Comptrollers", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 244, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 247, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1478, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 116, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 236, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 25, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_pendingOwner", + "offset": 0, + "slot": "101", + "type": "t_address" + }, + { + "astId": 104, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 4921, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_accessControlManager", + "offset": 0, + "slot": "151", + "type": "t_contract(IAccessControlManagerV8)5106" + }, + { + "astId": 4926, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 7563, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__deprecatedSlot1", + "offset": 0, + "slot": "201", + "type": "t_bytes32" + }, + { + "astId": 7570, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "poolAssetsFunds", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 7573, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__deprecatedSlot2", + "offset": 0, + "slot": "203", + "type": "t_bytes32" + }, + { + "astId": 7576, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__deprecatedSlot3", + "offset": 0, + "slot": "204", + "type": "t_bytes32" + }, + { + "astId": 7581, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "205", + "type": "t_array(t_uint256)46_storage" + }, + { + "astId": 7586, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "maxLoopsLimit", + "offset": 0, + "slot": "251", + "type": "t_uint256" + }, + { + "astId": 7591, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 7600, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "convertibleBaseAsset", + "offset": 0, + "slot": "301", + "type": "t_address" + }, + { + "astId": 7603, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "shortfall", + "offset": 0, + "slot": "302", + "type": "t_address" + }, + { + "astId": 7606, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "pancakeSwapRouter", + "offset": 0, + "slot": "303", + "type": "t_address" + }, + { + "astId": 7609, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "minAmountToConvert", + "offset": 0, + "slot": "304", + "type": "t_uint256" + }, + { + "astId": 547, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "_status", + "offset": 0, + "slot": "305", + "type": "t_uint256" + }, + { + "astId": 616, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "__gap", + "offset": 0, + "slot": "306", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 7618, + "contract": "contracts/ProtocolReserve/RiskFundV2.sol:RiskFundV2", + "label": "riskFundConverter", + "offset": 0, + "slot": "355", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)46_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[46]", + "numberOfBytes": "1472" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IAccessControlManagerV8)5106": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} diff --git a/deployments/bsctestnet/RiskFundV2_Proxy.json b/deployments/bsctestnet/RiskFundV2_Proxy.json new file mode 100644 index 00000000..fc6896c9 --- /dev/null +++ b/deployments/bsctestnet/RiskFundV2_Proxy.json @@ -0,0 +1,277 @@ +{ + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "receipt": { + "to": null, + "from": "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706", + "contractAddress": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "transactionIndex": 2, + "gasUsed": "888546", + "logsBloom": "0x1000000000000000000000000000000040000000000000000080000800000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000000000000000000000000000081000000000000800000000000000000800000002000008400000000000000800000000000000000002000000020000000000000000001040000000000004400000000000000000020000000000200000000000000002000000000000800000000000000000000000000", + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e", + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000665085ecc7bc1b59c9872d030f2bd6c724739709" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + }, + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000002ce1d0ffd7e869d9df33e28552b12ddded326706" + ], + "data": "0x", + "logIndex": 2, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + }, + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 3, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + }, + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 4, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + }, + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 5, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + }, + { + "transactionIndex": 2, + "blockNumber": 33267915, + "transactionHash": "0x137af09eb8dd07c3fdb64fc7dac3bf47ee320af3b8597d9f14b55763354fb075", + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007877ffd62649b6a1557b55d4c20fcbab17344c91", + "logIndex": 6, + "blockHash": "0x5a25a1167f00e0ed468211a97c958ad55c7aeccf6fa0ec154c4d85bb4f655f3e" + } + ], + "blockNumber": 33267915, + "cumulativeGasUsed": "1000882", + "status": 1, + "byzantium": true + }, + "args": [ + "0x665085EcC7bc1B59c9872d030f2Bd6c724739709", + "0x7877fFd62649b6A1557B55D4c20fcBaB17344C91", + "0x2a1d054700000000000000000000000083edf1dee1b730b7e8e13c00ba76027d63a51ac00000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000000000a11c8d9dc9b66e209ef60f0c8d969d3cd988782c00000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa0000000000000000000000000000000000000000000000000000000000000064" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} From 4e1f600cc023c263332a02c211ad11fafc9a9990 Mon Sep 17 00:00:00 2001 From: 0xlucian <0xlucian@users.noreply.github.com> Date: Thu, 14 Mar 2024 08:59:04 +0000 Subject: [PATCH 49/53] feat: updating deployment files --- deployments/bscmainnet.json | 917 ++++++++++++++++++++++++++ deployments/bscmainnet_addresses.json | 4 +- deployments/bsctestnet.json | 917 ++++++++++++++++++++++++++ deployments/bsctestnet_addresses.json | 4 +- 4 files changed, 1840 insertions(+), 2 deletions(-) diff --git a/deployments/bscmainnet.json b/deployments/bscmainnet.json index 9a01460f..05fd3756 100644 --- a/deployments/bscmainnet.json +++ b/deployments/bscmainnet.json @@ -6901,6 +6901,774 @@ ] }, "RiskFundV2": { + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "poolReserve", + "type": "uint256" + } + ], + "name": "InsufficientPoolReserve", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRiskFundConverter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortfallAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldConvertibleBaseAsset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newConvertibleBaseAsset", + "type": "address" + } + ], + "name": "ConvertibleBaseAssetUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "PoolAssetsDecreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "PoolAssetsIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldRiskFundConverter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newRiskFundConverter", + "type": "address" + } + ], + "name": "RiskFundConverterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldShortfallContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newShortfallContract", + "type": "address" + } + ], + "name": "ShortfallContractUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepTokenFromPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferredReserveForAuction", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "convertibleBaseAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolsBaseAssetReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "poolAssetsFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "riskFundConverter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "convertibleBaseAsset_", + "type": "address" + } + ], + "name": "setConvertibleBaseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "riskFundConverter_", + "type": "address" + } + ], + "name": "setRiskFundConverter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "shortfallContractAddress_", + "type": "address" + } + ], + "name": "setShortfallContractAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepTokenFromPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferReserveForAuction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "updatePoolState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "RiskFundV2_Implementation": { "address": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", "abi": [ { @@ -7524,6 +8292,155 @@ } ] }, + "RiskFundV2_Proxy": { + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, "SingleTokenConverterBeacon": { "address": "0x4c9D57b05B245c40235D720A5f3A592f3DfF11ca", "abi": [ diff --git a/deployments/bscmainnet_addresses.json b/deployments/bscmainnet_addresses.json index ea423864..50189542 100644 --- a/deployments/bscmainnet_addresses.json +++ b/deployments/bscmainnet_addresses.json @@ -14,7 +14,9 @@ "RiskFundConverter": "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0", "RiskFundConverter_Implementation": "0xd420Bf9C31F6b4a98875B6e561b13aCB19210647", "RiskFundConverter_Proxy": "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0", - "RiskFundV2": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", + "RiskFundV2": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "RiskFundV2_Implementation": "0x2F377545Fd095fA59A56Cb1fD7456A2a0B781Cb6", + "RiskFundV2_Proxy": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", "SingleTokenConverterBeacon": "0x4c9D57b05B245c40235D720A5f3A592f3DfF11ca", "SingleTokenConverterImp": "0x40ed28180Df01FdeB957224E4A5415704B9D5990", "USDCPrimeConverter": "0xa758c9C215B6c4198F0a0e3FA46395Fa15Db691b", diff --git a/deployments/bsctestnet.json b/deployments/bsctestnet.json index 5ad37e99..fad8acff 100644 --- a/deployments/bsctestnet.json +++ b/deployments/bsctestnet.json @@ -6901,6 +6901,774 @@ ] }, "RiskFundV2": { + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "poolReserve", + "type": "uint256" + } + ], + "name": "InsufficientPoolReserve", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRiskFundConverter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortfallAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldConvertibleBaseAsset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newConvertibleBaseAsset", + "type": "address" + } + ], + "name": "ConvertibleBaseAssetUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "PoolAssetsDecreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "PoolAssetsIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldRiskFundConverter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newRiskFundConverter", + "type": "address" + } + ], + "name": "RiskFundConverterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldShortfallContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newShortfallContract", + "type": "address" + } + ], + "name": "ShortfallContractUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepTokenFromPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferredReserveForAuction", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "convertibleBaseAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolsBaseAssetReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "poolAssetsFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "riskFundConverter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "convertibleBaseAsset_", + "type": "address" + } + ], + "name": "setConvertibleBaseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "riskFundConverter_", + "type": "address" + } + ], + "name": "setRiskFundConverter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "shortfallContractAddress_", + "type": "address" + } + ], + "name": "setShortfallContractAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepTokenFromPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferReserveForAuction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "updatePoolState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "RiskFundV2_Implementation": { "address": "0xcA2A023FBe3be30b7187E88D7FDE1A9a4358B509", "abi": [ { @@ -7476,6 +8244,155 @@ } ] }, + "RiskFundV2_Proxy": { + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, "SingleTokenConverterBeacon": { "address": "0xD2410D8B581D37c5B474CD9Ee0C15F02138AC028", "abi": [ diff --git a/deployments/bsctestnet_addresses.json b/deployments/bsctestnet_addresses.json index 478e5700..6f05d537 100644 --- a/deployments/bsctestnet_addresses.json +++ b/deployments/bsctestnet_addresses.json @@ -14,7 +14,9 @@ "RiskFundConverter": "0x32Fbf7bBbd79355B86741E3181ef8c1D9bD309Bb", "RiskFundConverter_Implementation": "0x857ebb8CAcb97DE5ab719320c9FB3aa16076bFe3", "RiskFundConverter_Proxy": "0x32Fbf7bBbd79355B86741E3181ef8c1D9bD309Bb", - "RiskFundV2": "0xcA2A023FBe3be30b7187E88D7FDE1A9a4358B509", + "RiskFundV2": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "RiskFundV2_Implementation": "0xcA2A023FBe3be30b7187E88D7FDE1A9a4358B509", + "RiskFundV2_Proxy": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", "SingleTokenConverterBeacon": "0xD2410D8B581D37c5B474CD9Ee0C15F02138AC028", "SingleTokenConverterImp": "0x42Ec3Eb6F23460dFDfa3aE5688f3415CDfE0C6AD", "USDCPrimeConverter": "0x2ecEdE6989d8646c992344fF6C97c72a3f811A13", From aa98e235feb46a951265ab2af7e5ef9769e2866b Mon Sep 17 00:00:00 2001 From: 0xlucian <0xluciandev@gmail.com> Date: Thu, 14 Mar 2024 11:02:27 +0200 Subject: [PATCH 50/53] fix: local deployment of RiskFund --- deploy/006-risk-fund-v2.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/deploy/006-risk-fund-v2.ts b/deploy/006-risk-fund-v2.ts index e081db94..f607d5f8 100644 --- a/deploy/006-risk-fund-v2.ts +++ b/deploy/006-risk-fund-v2.ts @@ -5,7 +5,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { multisigs } from "../helpers/utils"; const func: DeployFunction = async ({ - network: { name }, + network: { name, live }, getNamedAccounts, deployments, }: HardhatRuntimeEnvironment) => { @@ -27,13 +27,15 @@ const func: DeployFunction = async ({ log: true, }); - const targetOwner = (await ethers.getContractOrNull("NormalTimelock"))?.address || multisigs[name]; + if (live) { + const targetOwner = (await ethers.getContractOrNull("NormalTimelock"))?.address || multisigs[name]; - const contract = await ethers.getContract("RiskFundV2"); - if ((await contract.owner()) !== targetOwner && (await contract.pendingOwner()) !== targetOwner) { - console.log(`Transferring ownership of RiskFundV2 to ${targetOwner}`); - const tx = await contract.transferOwnership(targetOwner); - await tx.wait(); + const contract = await ethers.getContract("RiskFundV2"); + if ((await contract.owner()) !== targetOwner && (await contract.pendingOwner()) !== targetOwner) { + console.log(`Transferring ownership of RiskFundV2 to ${targetOwner}`); + const tx = await contract.transferOwnership(targetOwner); + await tx.wait(); + } } }; From 2bddd8ab2b0705d9e9b06b56d7f73edbaa680b15 Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Wed, 20 Mar 2024 11:40:53 +0000 Subject: [PATCH 51/53] chore(release): 1.5.0-dev.7 [skip ci] ## [1.5.0-dev.7](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.6...v1.5.0-dev.7) (2024-03-20) ### Features * updating deployment files ([4e1f600](https://github.com/VenusProtocol/protocol-reserve/commit/4e1f600cc023c263332a02c211ad11fafc9a9990)) ### Bug Fixes * local deployment of RiskFund ([aa98e23](https://github.com/VenusProtocol/protocol-reserve/commit/aa98e235feb46a951265ab2af7e5ef9769e2866b)) --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51343b8e..ef0367df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [1.5.0-dev.7](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.6...v1.5.0-dev.7) (2024-03-20) + + +### Features + +* updating deployment files ([4e1f600](https://github.com/VenusProtocol/protocol-reserve/commit/4e1f600cc023c263332a02c211ad11fafc9a9990)) + + +### Bug Fixes + +* local deployment of RiskFund ([aa98e23](https://github.com/VenusProtocol/protocol-reserve/commit/aa98e235feb46a951265ab2af7e5ef9769e2866b)) + ## [1.5.0-dev.6](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.5...v1.5.0-dev.6) (2024-03-14) diff --git a/package.json b/package.json index ff31603e..c68ef518 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@venusprotocol/protocol-reserve", "description": "Venus Protocol contracts to manage the income generated by the protocol", - "version": "1.5.0-dev.6", + "version": "1.5.0-dev.7", "author": "Venus", "engines": { "node": ">=18.0.0" From 151db00ef9c563f3aaa79af5e1f14d25d51837e1 Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Wed, 20 Mar 2024 11:27:23 -0300 Subject: [PATCH 52/53] refactor: remove unnecessary isolated pools dep --- hardhat.config.ts | 6 ------ package.json | 1 - yarn.lock | 17 ----------------- 3 files changed, 24 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 68280015..7d18b41e 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -25,32 +25,26 @@ const externalDeployments = { bsctestnet: [ "node_modules/@venusprotocol/governance-contracts/deployments/bsctestnet", "node_modules/@venusprotocol/oracle/deployments/bsctestnet", - "node_modules/@venusprotocol/isolated-pools/deployments/bsctestnet", ], sepolia: [ "node_modules/@venusprotocol/governance-contracts/deployments/sepolia", "node_modules/@venusprotocol/oracle/deployments/sepolia", - "node_modules/@venusprotocol/isolated-pools/deployments/sepolia", ], opbnbtestnet: [ "node_modules/@venusprotocol/governance-contracts/deployments/opbnbtestnet", "node_modules/@venusprotocol/oracle/deployments/opbnbtestnet", - "node_modules/@venusprotocol/isolated-pools/deployments/opbnbtestnet", ], bscmainnet: [ "node_modules/@venusprotocol/governance-contracts/deployments/bscmainnet", "node_modules/@venusprotocol/oracle/deployments/bscmainnet", - "node_modules/@venusprotocol/isolated-pools/deployments/bscmainnet", ], ethereum: [ "node_modules/@venusprotocol/governance-contracts/deployments/ethereum", "node_modules/@venusprotocol/oracle/deployments/ethereum", - "node_modules/@venusprotocol/isolated-pools/deployments/ethereum", ], opbnbmainnet: [ "node_modules/@venusprotocol/governance-contracts/deployments/opbnbmainnet", "node_modules/@venusprotocol/oracle/deployments/opbnbmainnet", - "node_modules/@venusprotocol/isolated-pools/deployments/opbnbmainnet", ], }; diff --git a/package.json b/package.json index c68ef518..16ee6ebf 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "@openzeppelin/contracts-upgradeable": "^4.8.3", "@openzeppelin/hardhat-upgrades": "^1.21.0", "@solidity-parser/parser": "^0.13.2", - "@venusprotocol/isolated-pools": "^2.6.0", "@venusprotocol/solidity-utilities": "^1.3.0", "ethers": "^5.7.0", "hardhat-deploy": "^0.11.14", diff --git a/yarn.lock b/yarn.lock index 7a4547d1..01162fbe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2953,22 +2953,6 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/isolated-pools@npm:^2.6.0": - version: 2.6.0 - resolution: "@venusprotocol/isolated-pools@npm:2.6.0" - dependencies: - "@nomiclabs/hardhat-ethers": ^2.2.3 - "@openzeppelin/contracts": ^4.8.3 - "@openzeppelin/contracts-upgradeable": ^4.8.3 - "@openzeppelin/hardhat-upgrades": ^1.21.0 - "@solidity-parser/parser": ^0.13.2 - ethers: ^5.7.0 - hardhat-deploy: ^0.11.14 - module-alias: ^2.2.2 - checksum: 324bdaa9d6de3f812800f78429d4f35812fc5d71a9127b6c6726e5f7b20924b074d5ed2935cf0c4977f0db053624ad9ba27e9207184bcd4672dd9ead3986ba12 - languageName: node - linkType: hard - "@venusprotocol/oracle@npm:^1.10.0": version: 1.10.0 resolution: "@venusprotocol/oracle@npm:1.10.0" @@ -3036,7 +3020,6 @@ __metadata: "@typescript-eslint/eslint-plugin": ^5.44.0 "@typescript-eslint/parser": ^5.44.0 "@venusprotocol/governance-contracts": ^1.4.0 - "@venusprotocol/isolated-pools": ^2.6.0 "@venusprotocol/oracle": ^1.10.0 "@venusprotocol/solidity-utilities": ^1.3.0 bignumber.js: ^9.1.1 From 113ce123b20d8b122bff04350fd9e5653dbf5697 Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Wed, 20 Mar 2024 14:37:43 +0000 Subject: [PATCH 53/53] chore(release): 1.5.0-dev.8 [skip ci] ## [1.5.0-dev.8](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.7...v1.5.0-dev.8) (2024-03-20) --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef0367df..a5be01e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## [1.5.0-dev.8](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.7...v1.5.0-dev.8) (2024-03-20) + ## [1.5.0-dev.7](https://github.com/VenusProtocol/protocol-reserve/compare/v1.5.0-dev.6...v1.5.0-dev.7) (2024-03-20) diff --git a/package.json b/package.json index 16ee6ebf..b9dcf885 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@venusprotocol/protocol-reserve", "description": "Venus Protocol contracts to manage the income generated by the protocol", - "version": "1.5.0-dev.7", + "version": "1.5.0-dev.8", "author": "Venus", "engines": { "node": ">=18.0.0"